diff --git a/lib/common/widgets/dynamic_sliver_appbar.dart b/lib/common/widgets/dynamic_sliver_appbar.dart deleted file mode 100644 index 99e78286..00000000 --- a/lib/common/widgets/dynamic_sliver_appbar.dart +++ /dev/null @@ -1,180 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -/// https://github.com/flutter/flutter/issues/18345#issuecomment-1627644396 -class DynamicSliverAppBar extends StatefulWidget { - const DynamicSliverAppBar({ - this.flexibleSpace, - super.key, - this.leading, - this.automaticallyImplyLeading = true, - this.title, - this.actions, - this.bottom, - this.elevation, - this.scrolledUnderElevation, - this.shadowColor, - this.surfaceTintColor, - this.forceElevated = false, - this.backgroundColor, - this.backgroundGradient, - this.foregroundColor, - this.iconTheme, - this.actionsIconTheme, - this.primary = true, - this.centerTitle, - this.excludeHeaderSemantics = false, - this.titleSpacing, - this.collapsedHeight, - this.expandedHeight, - this.floating = false, - this.pinned = false, - this.snap = false, - this.stretch = false, - this.stretchTriggerOffset = 100.0, - this.onStretchTrigger, - this.shape, - this.toolbarHeight = kToolbarHeight, - this.leadingWidth, - this.toolbarTextStyle, - this.titleTextStyle, - this.systemOverlayStyle, - this.forceMaterialTransparency = false, - this.clipBehavior, - this.appBarClipper, - this.callback, - }); - - final ValueChanged? callback; - final Widget? flexibleSpace; - final Widget? leading; - final bool automaticallyImplyLeading; - final Widget? title; - final List? actions; - final PreferredSizeWidget? bottom; - final double? elevation; - final double? scrolledUnderElevation; - final Color? shadowColor; - final Color? surfaceTintColor; - final bool forceElevated; - final Color? backgroundColor; - - /// If backgroundGradient is non null, backgroundColor will be ignored - final LinearGradient? backgroundGradient; - final Color? foregroundColor; - final IconThemeData? iconTheme; - final IconThemeData? actionsIconTheme; - final bool primary; - final bool? centerTitle; - final bool excludeHeaderSemantics; - final double? titleSpacing; - final double? expandedHeight; - final double? collapsedHeight; - final bool floating; - final bool pinned; - final ShapeBorder? shape; - final double toolbarHeight; - final double? leadingWidth; - final TextStyle? toolbarTextStyle; - final TextStyle? titleTextStyle; - final SystemUiOverlayStyle? systemOverlayStyle; - final bool forceMaterialTransparency; - final Clip? clipBehavior; - final bool snap; - final bool stretch; - final double stretchTriggerOffset; - final AsyncCallback? onStretchTrigger; - final CustomClipper? appBarClipper; - - @override - State createState() => _DynamicSliverAppBarState(); -} - -class _DynamicSliverAppBarState extends State { - final GlobalKey _childKey = GlobalKey(); - - // As long as the height is 0 instead of the sliver app bar a sliver to box adapter will be used - // to calculate dynamically the size for the sliver app bar - double _height = 0; - - @override - void initState() { - super.initState(); - _updateHeight(); - } - - void _updateHeight() { - // Gets the new height and updates the sliver app bar. Needs to be called after the last frame has been rebuild - // otherwise this will throw an error - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - if (_childKey.currentContext == null) return; - setState(() { - _height = (_childKey.currentContext!.findRenderObject()! as RenderBox) - .size - .height; - widget.callback?.call(_height); - }); - }); - } - - @override - void didChangeDependencies() { - _height = 0; - _updateHeight(); - super.didChangeDependencies(); - } - - @override - Widget build(BuildContext context) { - //Needed to lay out the flexibleSpace the first time, so we can calculate its intrinsic height - if (_height == 0) { - return SliverToBoxAdapter( - child: SizedBox( - key: _childKey, - child: widget.flexibleSpace ?? const SizedBox(height: kToolbarHeight), - ), - ); - } - - MediaQuery.orientationOf(context); - - return SliverAppBar( - leading: widget.leading, - automaticallyImplyLeading: widget.automaticallyImplyLeading, - title: widget.title, - actions: widget.actions, - bottom: widget.bottom, - elevation: widget.elevation, - scrolledUnderElevation: widget.scrolledUnderElevation, - shadowColor: widget.shadowColor, - surfaceTintColor: widget.surfaceTintColor, - forceElevated: widget.forceElevated, - backgroundColor: widget.backgroundColor, - foregroundColor: widget.foregroundColor, - iconTheme: widget.iconTheme, - actionsIconTheme: widget.actionsIconTheme, - primary: widget.primary, - centerTitle: widget.centerTitle, - excludeHeaderSemantics: widget.excludeHeaderSemantics, - titleSpacing: widget.titleSpacing, - collapsedHeight: widget.collapsedHeight, - floating: widget.floating, - pinned: widget.pinned, - snap: widget.snap, - stretch: widget.stretch, - stretchTriggerOffset: widget.stretchTriggerOffset, - onStretchTrigger: widget.onStretchTrigger, - shape: widget.shape, - toolbarHeight: widget.toolbarHeight, - expandedHeight: _height, - leadingWidth: widget.leadingWidth, - toolbarTextStyle: widget.toolbarTextStyle, - titleTextStyle: widget.titleTextStyle, - systemOverlayStyle: widget.systemOverlayStyle, - forceMaterialTransparency: widget.forceMaterialTransparency, - clipBehavior: widget.clipBehavior, - flexibleSpace: FlexibleSpaceBar(background: widget.flexibleSpace), - ); - } -} diff --git a/lib/common/widgets/dynamic_sliver_appbar_medium.dart b/lib/common/widgets/dynamic_sliver_appbar_medium.dart index 900bb1c8..333ea738 100644 --- a/lib/common/widgets/dynamic_sliver_appbar_medium.dart +++ b/lib/common/widgets/dynamic_sliver_appbar_medium.dart @@ -99,12 +99,6 @@ class _DynamicSliverAppBarMediumState extends State { // to calculate dynamically the size for the sliver app bar double _height = 0; - @override - void initState() { - super.initState(); - _updateHeight(); - } - void _updateHeight() { // Gets the new height and updates the sliver app bar. Needs to be called after the last frame has been rebuild // otherwise this will throw an error @@ -120,26 +114,39 @@ class _DynamicSliverAppBarMediumState extends State { } Orientation? _orientation; + late Size size; @override - Widget build(BuildContext context) { - final orientation = MediaQuery.orientationOf(context); + void didChangeDependencies() { + super.didChangeDependencies(); + size = MediaQuery.sizeOf(context); + final orientation = size.width > size.height + ? Orientation.landscape + : Orientation.portrait; if (orientation != _orientation) { _orientation = orientation; _height = 0; _updateHeight(); } + } + @override + Widget build(BuildContext context) { //Needed to lay out the flexibleSpace the first time, so we can calculate its intrinsic height if (_height == 0) { return SliverToBoxAdapter( - child: SizedBox( - key: _childKey, - child: widget.flexibleSpace ?? const SizedBox(height: kToolbarHeight), + child: UnconstrainedBox( + alignment: Alignment.topLeft, + child: SizedBox( + key: _childKey, + width: size.width, + child: widget.flexibleSpace, + ), ), ); } + final padding = MediaQuery.paddingOf(context).top; return SliverAppBar.medium( leading: widget.leading, automaticallyImplyLeading: widget.automaticallyImplyLeading, @@ -159,7 +166,6 @@ class _DynamicSliverAppBarMediumState extends State { centerTitle: widget.centerTitle, excludeHeaderSemantics: widget.excludeHeaderSemantics, titleSpacing: widget.titleSpacing, - collapsedHeight: widget.collapsedHeight, floating: widget.floating, pinned: widget.pinned, snap: widget.snap, @@ -167,8 +173,9 @@ class _DynamicSliverAppBarMediumState extends State { stretchTriggerOffset: widget.stretchTriggerOffset, onStretchTrigger: widget.onStretchTrigger, shape: widget.shape, - toolbarHeight: widget.toolbarHeight, - expandedHeight: _height - MediaQuery.paddingOf(context).top, + toolbarHeight: kToolbarHeight, + collapsedHeight: kToolbarHeight + padding + 1, + expandedHeight: _height - padding, leadingWidth: widget.leadingWidth, toolbarTextStyle: widget.toolbarTextStyle, titleTextStyle: widget.titleTextStyle, diff --git a/lib/pages/dynamics_topic/view.dart b/lib/pages/dynamics_topic/view.dart index 37bf391e..86ce4566 100644 --- a/lib/pages/dynamics_topic/view.dart +++ b/lib/pages/dynamics_topic/view.dart @@ -42,6 +42,7 @@ class _DynTopicPageState extends State { @override Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); + final padding = MediaQuery.paddingOf(context); return Scaffold( resizeToAvoidBottomInset: false, floatingActionButton: FloatingActionButton.extended( @@ -70,7 +71,13 @@ class _DynTopicPageState extends State { controller: _controller.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ - Obx(() => _buildAppBar(theme, _controller.topState.value)), + Obx( + () => _buildAppBar( + theme, + padding.top, + _controller.topState.value, + ), + ), Obx(() { final allSortBy = _controller.topicSortByConf.value?.allSortBy; if (allSortBy != null && allSortBy.isNotEmpty) { @@ -133,9 +140,7 @@ class _DynTopicPageState extends State { return const SliverToBoxAdapter(); }), SliverPadding( - padding: EdgeInsets.only( - bottom: MediaQuery.paddingOf(context).bottom + 80, - ), + padding: EdgeInsets.only(bottom: padding.bottom + 80), sliver: Obx(() => _buildBody(_controller.loadingState.value)), ), ], @@ -145,15 +150,18 @@ class _DynTopicPageState extends State { ); } - Widget _buildAppBar(ThemeData theme, LoadingState topState) { - late final paddingTop = MediaQuery.paddingOf(context).top; + Widget _buildAppBar( + ThemeData theme, + double paddingTop, + LoadingState topState, + ) { return switch (topState) { Loading() => const SliverAppBar(), Success(:var response) when (topState.dataOrNull != null) => DynamicSliverAppBarMedium( pinned: true, - callback: (value) => _controller.appbarOffset = - value - kToolbarHeight - paddingTop - 7, + callback: (value) => + _controller.appbarOffset = value - kToolbarHeight - paddingTop, title: IgnorePointer(child: Text(response!.topicItem!.name)), flexibleSpace: Container( decoration: BoxDecoration( diff --git a/lib/pages/member/controller.dart b/lib/pages/member/controller.dart index c1d54698..443ad2cd 100644 --- a/lib/pages/member/controller.dart +++ b/lib/pages/member/controller.dart @@ -47,7 +47,6 @@ class MemberController extends CommonDataController final fromViewAid = Get.parameters['from_view_aid']; final key = GlobalKey(); - int offset = 120; @override void onInit() { diff --git a/lib/pages/member/view.dart b/lib/pages/member/view.dart index 437456c4..e7d9a8b2 100644 --- a/lib/pages/member/view.dart +++ b/lib/pages/member/view.dart @@ -1,5 +1,5 @@ import 'package:PiliPlus/common/widgets/dialog/report_member.dart'; -import 'package:PiliPlus/common/widgets/dynamic_sliver_appbar.dart'; +import 'package:PiliPlus/common/widgets/dynamic_sliver_appbar_medium.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/http/loading_state.dart'; @@ -43,277 +43,236 @@ class _MemberPageState extends State { MemberController(mid: _mid), tag: _heroTag, ); - _userController.scrollController.addListener(listener); - } - - void listener() { - if (_userController.scrollController.hasClients) { - _userController.showUname.value = - _userController.scrollController.offset >= _userController.offset; - } - } - - @override - void dispose() { - _userController.scrollController.removeListener(listener); - super.dispose(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); - return Scaffold( - extendBody: true, - extendBodyBehindAppBar: true, - resizeToAvoidBottomInset: false, - appBar: AppBar( - forceMaterialTransparency: true, - title: IgnorePointer( - child: Obx( - () => - _userController.showUname.value && - _userController.username != null - ? Text(_userController.username!) - : const SizedBox.shrink(), - ), - ), - actions: [ - IconButton( - tooltip: '搜索', - onPressed: () => Get.toNamed( - '/memberSearch?mid=$_mid&uname=${_userController.username}', - ), - icon: const Icon(Icons.search_outlined), - ), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (BuildContext context) => [ - if (_userController.accountService.isLogin.value && - _userController.accountService.mid != _mid) ...[ - PopupMenuItem( - onTap: () => _userController.blockUser(context), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.block, size: 19), - const SizedBox(width: 10), - Text( - _userController.relation.value != 128 - ? '加入黑名单' - : '移除黑名单', - ), - ], - ), + return Material( + color: theme.colorScheme.surface, + child: Obx(() { + if (_userController.loadingState.value.isSuccess) { + return ExtendedNestedScrollView( + key: _userController.key, + controller: _userController.scrollController, + onlyOneScrollInBody: true, + pinnedHeaderSliverHeightBuilder: () => + kToolbarHeight + MediaQuery.paddingOf(context).top, + headerSliverBuilder: (context, innerBoxIsScrolled) { + return [ + _buildUserInfo( + theme, + _userController.loadingState.value, ), - if (_userController.isFollowed == 1) - PopupMenuItem( - onTap: _userController.onRemoveFan, - child: const Row( - mainAxisSize: MainAxisSize.min, + ]; + }, + body: _userController.tab2?.isNotEmpty == true + ? SafeArea( + top: false, + bottom: false, + child: Column( children: [ - Icon(Icons.remove_circle_outline_outlined, size: 19), - SizedBox(width: 10), - Text('移除粉丝'), + if ((_userController.tab2?.length ?? 0) > 1) + TabBar( + controller: _userController.tabController, + tabs: _userController.tabs, + onTap: _userController.onTapTab, + ), + Expanded(child: _buildBody), ], ), - ), - ], - PopupMenuItem( - onTap: () => _userController.shareUser(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.share_outlined, size: 19), - const SizedBox(width: 10), - Text( - _userController.accountService.mid != _mid - ? '分享UP主' - : '分享我的主页', - ), - ], - ), - ), - PopupMenuItem( - onTap: () => Get.toNamed( - '/upowerRank', - parameters: { - 'mid': _userController.mid.toString(), - }, - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.electric_bolt, size: 19), - SizedBox(width: 10), - Text('充电排行榜'), - ], - ), - ), - if (_userController.accountService.isLogin.value) - if (_userController.mid == - _userController.accountService.mid) ...[ - if ((_userController - .loadingState - .value - .dataOrNull - ?.card - ?.vip - ?.status ?? - 0) > - 0) - PopupMenuItem( - onTap: _userController.vipExpAdd, - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.upcoming_outlined, size: 19), - SizedBox(width: 10), - Text('大会员经验'), - ], - ), - ), - PopupMenuItem( - onTap: () => Get.to( - const LogPage(), - arguments: LoginLogController(), - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.login, size: 18), - SizedBox(width: 10), - Text('登录记录'), - ], - ), - ), - PopupMenuItem( - onTap: () => Get.to( - const LogPage(), - arguments: CoinLogController(), - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(FontAwesomeIcons.b, size: 16), - SizedBox(width: 10), - Text('硬币记录'), - ], - ), - ), - PopupMenuItem( - onTap: () => Get.to( - const LogPage(), - arguments: ExpLogController(), - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.linear_scale, size: 18), - SizedBox(width: 10), - Text('经验记录'), - ], - ), - ), - PopupMenuItem( - onTap: () => Get.toNamed('/spaceSetting'), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.settings_outlined, size: 19), - SizedBox(width: 10), - Text('空间设置'), - ], - ), - ), - ] else ...[ - const PopupMenuDivider(), - PopupMenuItem( - onTap: () => showDialog( - context: context, - builder: (context) => AlertDialog( - clipBehavior: Clip.hardEdge, - contentPadding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 16, - ), - content: MemberReportPanel( - name: _userController.username, - mid: _mid, - ), - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.error_outline, - size: 19, - color: theme.colorScheme.error, - ), - const SizedBox(width: 10), - Text( - '举报', - style: TextStyle(color: theme.colorScheme.error), - ), - ], - ), - ), - ], - ], - ), - const SizedBox(width: 4), - ], - ), - body: Obx( - () => _userController.loadingState.value.isSuccess - ? LayoutBuilder( - builder: (context, constraints) { - return ExtendedNestedScrollView( - key: _userController.key, - controller: _userController.scrollController, - onlyOneScrollInBody: true, - pinnedHeaderSliverHeightBuilder: () { - return kToolbarHeight + - MediaQuery.paddingOf(this.context).top.toInt(); - }, - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - _buildAppBar( - isV: constraints.maxHeight > constraints.maxWidth, - ), - ]; - }, - body: _userController.tab2?.isNotEmpty == true - ? SafeArea( - top: false, - bottom: false, - child: Column( - children: [ - if ((_userController.tab2?.length ?? 0) > 1) - _buildTab(theme), - Expanded(child: _buildBody), - ], - ), - ) - : const Center(child: Text('EMPTY')), - ); - }, - ) - : Center( - child: _buildUserInfo(_userController.loadingState.value), - ), - ), + ) + : const Center(child: Text('EMPTY')), + ); + } + return Center( + child: _buildUserInfo(theme, _userController.loadingState.value), + ); + }), ); } - Widget _buildTab(ThemeData theme) => Material( - color: theme.colorScheme.surface, - child: TabBar( - controller: _userController.tabController, - tabs: _userController.tabs, - onTap: _userController.onTapTab, + List _actions(ThemeData theme) => [ + IconButton( + tooltip: '搜索', + onPressed: () => Get.toNamed( + '/memberSearch?mid=$_mid&uname=${_userController.username}', + ), + icon: const Icon(Icons.search_outlined), ), - ); + PopupMenuButton( + icon: const Icon(Icons.more_vert), + itemBuilder: (BuildContext context) => [ + if (_userController.accountService.isLogin.value && + _userController.accountService.mid != _mid) ...[ + PopupMenuItem( + onTap: () => _userController.blockUser(context), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.block, size: 19), + const SizedBox(width: 10), + Text( + _userController.relation.value != 128 ? '加入黑名单' : '移除黑名单', + ), + ], + ), + ), + if (_userController.isFollowed == 1) + PopupMenuItem( + onTap: _userController.onRemoveFan, + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.remove_circle_outline_outlined, size: 19), + SizedBox(width: 10), + Text('移除粉丝'), + ], + ), + ), + ], + PopupMenuItem( + onTap: () => _userController.shareUser(), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.share_outlined, size: 19), + const SizedBox(width: 10), + Text( + _userController.accountService.mid != _mid ? '分享UP主' : '分享我的主页', + ), + ], + ), + ), + PopupMenuItem( + onTap: () => Get.toNamed( + '/upowerRank', + parameters: { + 'mid': _userController.mid.toString(), + }, + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.electric_bolt, size: 19), + SizedBox(width: 10), + Text('充电排行榜'), + ], + ), + ), + if (_userController.accountService.isLogin.value) + if (_userController.mid == _userController.accountService.mid) ...[ + if ((_userController + .loadingState + .value + .dataOrNull + ?.card + ?.vip + ?.status ?? + 0) > + 0) + PopupMenuItem( + onTap: _userController.vipExpAdd, + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.upcoming_outlined, size: 19), + SizedBox(width: 10), + Text('大会员经验'), + ], + ), + ), + PopupMenuItem( + onTap: () => Get.to( + const LogPage(), + arguments: LoginLogController(), + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.login, size: 18), + SizedBox(width: 10), + Text('登录记录'), + ], + ), + ), + PopupMenuItem( + onTap: () => Get.to( + const LogPage(), + arguments: CoinLogController(), + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(FontAwesomeIcons.b, size: 16), + SizedBox(width: 10), + Text('硬币记录'), + ], + ), + ), + PopupMenuItem( + onTap: () => Get.to( + const LogPage(), + arguments: ExpLogController(), + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.linear_scale, size: 18), + SizedBox(width: 10), + Text('经验记录'), + ], + ), + ), + PopupMenuItem( + onTap: () => Get.toNamed('/spaceSetting'), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.settings_outlined, size: 19), + SizedBox(width: 10), + Text('空间设置'), + ], + ), + ), + ] else ...[ + const PopupMenuDivider(), + PopupMenuItem( + onTap: () => showDialog( + context: context, + builder: (context) => AlertDialog( + clipBehavior: Clip.hardEdge, + contentPadding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 16, + ), + content: MemberReportPanel( + name: _userController.username, + mid: _mid, + ), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.error_outline, + size: 19, + color: theme.colorScheme.error, + ), + const SizedBox(width: 10), + Text( + '举报', + style: TextStyle(color: theme.colorScheme.error), + ), + ], + ), + ), + ], + ], + ), + const SizedBox(width: 4), + ]; Widget get _buildBody => tabBarView( controller: _userController.tabController, @@ -345,48 +304,44 @@ class _MemberPageState extends State { }).toList(), ); - Widget _buildAppBar({bool isV = true}) { - final top = MediaQuery.paddingOf(context).top; - return DynamicSliverAppBar( - pinned: true, - primary: false, - automaticallyImplyLeading: false, - toolbarHeight: kToolbarHeight + top, - flexibleSpace: _buildUserInfo(_userController.loadingState.value, isV), - callback: (value) { - _userController.offset = (value - 56 - top).toInt(); - listener(); - }, - ); - } - - Widget _buildUserInfo(LoadingState userState, [bool isV = true]) { - return switch (userState) { - Loading() => const CircularProgressIndicator(), - Success(:var response) => - response != null - ? Obx( - () => UserInfoCard( - isV: isV, - isOwner: - _userController.mid == _userController.accountService.mid, - relation: _userController.relation.value, - card: response.card!, - images: response.images!, - onFollow: () => _userController.onFollow(context), - live: _userController.live, - silence: _userController.silence, - ), - ) - : GestureDetector( - onTap: _userController.onReload, - behavior: HitTestBehavior.opaque, - child: const SizedBox(height: 56, width: double.infinity), + Widget _buildUserInfo(ThemeData theme, LoadingState userState) { + switch (userState) { + case Loading(): + return const CircularProgressIndicator(); + case Success(:var response): + if (response != null) { + return DynamicSliverAppBarMedium( + pinned: true, + actions: _actions(theme), + title: Text(_userController.username ?? ''), + flexibleSpace: Obx( + () => UserInfoCard( + isOwner: + _userController.mid == _userController.accountService.mid, + relation: _userController.relation.value, + card: response.card!, + images: response.images!, + onFollow: () => _userController.onFollow(context), + live: _userController.live, + silence: _userController.silence, ), - Error(:var errMsg) => scrollErrorWidget( - errMsg: errMsg, - onReload: _userController.onReload, - ), - }; + ), + ); + } + return SliverAppBar( + pinned: true, + actions: _actions(theme), + title: GestureDetector( + onTap: _userController.onReload, + behavior: HitTestBehavior.opaque, + child: Text(_userController.username ?? ''), + ), + ); + case Error(:var errMsg): + return scrollErrorWidget( + errMsg: errMsg, + onReload: _userController.onReload, + ); + } } } diff --git a/lib/pages/member/widget/user_info_card.dart b/lib/pages/member/widget/user_info_card.dart index 3dbda32a..8e21592a 100644 --- a/lib/pages/member/widget/user_info_card.dart +++ b/lib/pages/member/widget/user_info_card.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/models_new/space/space/card.dart'; import 'package:PiliPlus/models_new/space/space/images.dart'; import 'package:PiliPlus/models_new/space/space/live.dart'; import 'package:PiliPlus/utils/accounts.dart'; +import 'package:PiliPlus/utils/context_ext.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/image_util.dart'; import 'package:PiliPlus/utils/num_util.dart'; @@ -12,12 +13,11 @@ import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide ContextExtensionss; class UserInfoCard extends StatelessWidget { const UserInfoCard({ super.key, - required this.isV, required this.isOwner, required this.card, required this.images, @@ -27,7 +27,6 @@ class UserInfoCard extends StatelessWidget { this.silence, }); - final bool isV; final bool isOwner; final int relation; final SpaceCard card; @@ -39,7 +38,9 @@ class UserInfoCard extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); - return isV ? _buildV(context, theme) : _buildH(context, theme); + return context.isPortrait + ? _buildV(context, theme) + : _buildH(context, theme); } Widget _countWidget({ @@ -541,11 +542,8 @@ class UserInfoCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ // _buildHeader(context), - SizedBox( - height: Get.mediaQuery.padding.top + 56, - ), + const SizedBox(height: 56), SafeArea( - top: false, bottom: false, child: Row( children: [