diff --git a/lib/common/widgets/image/custom_grid_view.dart b/lib/common/widgets/image/custom_grid_view.dart index c31df1be8..10b9a989d 100644 --- a/lib/common/widgets/image/custom_grid_view.dart +++ b/lib/common/widgets/image/custom_grid_view.dart @@ -205,10 +205,10 @@ class CustomGridView extends StatelessWidget { final radius = borderRadius(column, length, index); return LayoutId( id: index, - child: Hero( - tag: item.url, - child: GestureDetector( - onTap: () => onTap(context, index), + child: GestureDetector( + onTap: () => onTap(context, index), + child: Hero( + tag: item.url, child: Stack( clipBehavior: Clip.none, alignment: Alignment.center, diff --git a/lib/http/api.dart b/lib/http/api.dart index 9c76382a2..4033d550e 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -978,4 +978,7 @@ abstract final class Api { static const String followeeVotes = '${HttpString.tUrl}/vote_svr/v1/vote_svr/followee_votes'; + + static const String liveContributionRank = + '${HttpString.liveBaseUrl}/xlive/general-interface/v1/rank/queryContributionRank'; } diff --git a/lib/http/live.dart b/lib/http/live.dart index 2b834e10e..6cec38d6a 100644 --- a/lib/http/live.dart +++ b/lib/http/live.dart @@ -5,9 +5,11 @@ import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/login.dart'; import 'package:PiliPlus/http/ua_type.dart'; import 'package:PiliPlus/models/common/account_type.dart'; -import 'package:PiliPlus/models/common/live_search_type.dart'; +import 'package:PiliPlus/models/common/live/live_contribution_rank_type.dart'; +import 'package:PiliPlus/models/common/live/live_search_type.dart'; import 'package:PiliPlus/models_new/live/live_area_list/area_item.dart'; import 'package:PiliPlus/models_new/live/live_area_list/area_list.dart'; +import 'package:PiliPlus/models_new/live/live_contribution_rank/data.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/data.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/shield_info.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/shield_user_list.dart'; @@ -658,4 +660,34 @@ abstract final class LiveHttp { return Error(res.data['message']); } } + + static Future> liveContributionRank({ + required Object ruid, + required Object roomId, + required int page, + required LiveContributionRankType type, + }) async { + final res = await Request().get( + Api.liveContributionRank, + queryParameters: await WbiSign.makSign({ + 'ruid': ruid, + 'room_id': roomId, + 'page': page, + 'page_size': 100, + 'type': type.name, + 'switch': type.sw1tch, + 'platform': 'web', + 'web_location': 444.8, + }), + ); + if (res.data['code'] == 0) { + try { + return Success(LiveContributionRankData.fromJson(res.data['data'])); + } catch (e, s) { + return Error('$e\n\n$s'); + } + } else { + return Error(res.data['message']); + } + } } diff --git a/lib/models/common/live/live_contribution_rank_type.dart b/lib/models/common/live/live_contribution_rank_type.dart new file mode 100644 index 000000000..0a688eb10 --- /dev/null +++ b/lib/models/common/live/live_contribution_rank_type.dart @@ -0,0 +1,13 @@ +// ignore_for_file: constant_identifier_names + +enum LiveContributionRankType { + online_rank('在线榜', 'contribution_rank'), + daily_rank('日榜', 'today_rank'), + weekly_rank('周榜', 'current_week_rank'), + monthly_rank('月榜', 'current_month_rank') + ; + + final String title; + final String sw1tch; + const LiveContributionRankType(this.title, this.sw1tch); +} diff --git a/lib/models/common/live_dm_silent_type.dart b/lib/models/common/live/live_dm_silent_type.dart similarity index 100% rename from lib/models/common/live_dm_silent_type.dart rename to lib/models/common/live/live_dm_silent_type.dart diff --git a/lib/models/common/live_search_type.dart b/lib/models/common/live/live_search_type.dart similarity index 100% rename from lib/models/common/live_search_type.dart rename to lib/models/common/live/live_search_type.dart diff --git a/lib/models_new/live/live_contribution_rank/data.dart b/lib/models_new/live/live_contribution_rank/data.dart new file mode 100644 index 000000000..54e4ce69b --- /dev/null +++ b/lib/models_new/live/live_contribution_rank/data.dart @@ -0,0 +1,19 @@ +import 'package:PiliPlus/models_new/live/live_contribution_rank/item.dart'; + +class LiveContributionRankData { + List? item; + + LiveContributionRankData({ + this.item, + }); + + factory LiveContributionRankData.fromJson(Map json) => + LiveContributionRankData( + item: (json['item'] as List?) + ?.map( + (e) => + LiveContributionRankItem.fromJson(e as Map), + ) + .toList(), + ); +} diff --git a/lib/models_new/live/live_contribution_rank/item.dart b/lib/models_new/live/live_contribution_rank/item.dart new file mode 100644 index 000000000..e4f43c707 --- /dev/null +++ b/lib/models_new/live/live_contribution_rank/item.dart @@ -0,0 +1,31 @@ +import 'package:PiliPlus/models_new/live/live_contribution_rank/medal_info.dart'; + +class LiveContributionRankItem { + int? uid; + String? name; + String? face; + int? rank; + int? score; + MedalInfo? medalInfo; + + LiveContributionRankItem({ + this.uid, + this.name, + this.face, + this.rank, + this.score, + this.medalInfo, + }); + + factory LiveContributionRankItem.fromJson(Map json) => + LiveContributionRankItem( + uid: json['uid'] as int?, + name: json['name'] as String?, + face: json['face'] as String?, + rank: json['rank'] as int?, + score: json['score'] as int?, + medalInfo: json['medal_info'] == null + ? null + : MedalInfo.fromJson(json['medal_info'] as Map), + ); +} diff --git a/lib/models_new/live/live_contribution_rank/medal_info.dart b/lib/models_new/live/live_contribution_rank/medal_info.dart new file mode 100644 index 000000000..2c4c16716 --- /dev/null +++ b/lib/models_new/live/live_contribution_rank/medal_info.dart @@ -0,0 +1,14 @@ +class MedalInfo { + String? medalName; + int? level; + + MedalInfo({ + this.medalName, + this.level, + }); + + factory MedalInfo.fromJson(Map json) => MedalInfo( + medalName: json['medal_name'] as String?, + level: json['level'] as int?, + ); +} diff --git a/lib/pages/article/widgets/html_render.dart b/lib/pages/article/widgets/html_render.dart index 76b0e9320..859bd9c25 100644 --- a/lib/pages/article/widgets/html_render.dart +++ b/lib/pages/article/widgets/html_render.dart @@ -46,13 +46,13 @@ Widget htmlRender({ ); } final size = isEmote ? 22.0 : null; - return Hero( - tag: imgUrl, - child: GestureDetector( - onTap: () => PageUtils.imageView( - imgList: [SourceModel(url: imgUrl)], - quality: 60, - ), + return GestureDetector( + onTap: () => PageUtils.imageView( + imgList: [SourceModel(url: imgUrl)], + quality: 60, + ), + child: Hero( + tag: imgUrl, child: CachedNetworkImage( width: size, height: size, diff --git a/lib/pages/article/widgets/opus_content.dart b/lib/pages/article/widgets/opus_content.dart index a09655c58..958a43ae0 100644 --- a/lib/pages/article/widgets/opus_content.dart +++ b/lib/pages/article/widgets/opus_content.dart @@ -220,14 +220,14 @@ class OpusContent extends StatelessWidget { final height = width == null || pic.height == null ? null : width * pic.height! / pic.width!; - return Hero( - tag: pic.url!, - child: GestureDetector( - onTap: () => PageUtils.imageView( - imgList: [SourceModel(url: pic.url!)], - quality: 60, - ), - child: Center( + return GestureDetector( + onTap: () => PageUtils.imageView( + imgList: [SourceModel(url: pic.url!)], + quality: 60, + ), + child: Center( + child: Hero( + tag: pic.url!, child: CachedNetworkImage( width: width, height: height, diff --git a/lib/pages/live_dm_block/controller.dart b/lib/pages/live_dm_block/controller.dart index 11c6c0d7a..46e285272 100644 --- a/lib/pages/live_dm_block/controller.dart +++ b/lib/pages/live_dm_block/controller.dart @@ -1,6 +1,6 @@ import 'package:PiliPlus/http/live.dart'; import 'package:PiliPlus/http/loading_state.dart'; -import 'package:PiliPlus/models/common/live_dm_silent_type.dart'; +import 'package:PiliPlus/models/common/live/live_dm_silent_type.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/shield_user_list.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/pages/live_dm_block/view.dart b/lib/pages/live_dm_block/view.dart index aadf28e37..b4ab133b7 100644 --- a/lib/pages/live_dm_block/view.dart +++ b/lib/pages/live_dm_block/view.dart @@ -3,7 +3,7 @@ import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; -import 'package:PiliPlus/models/common/live_dm_silent_type.dart'; +import 'package:PiliPlus/models/common/live/live_dm_silent_type.dart'; import 'package:PiliPlus/models_new/live/live_dm_block/shield_user_list.dart'; import 'package:PiliPlus/pages/live_dm_block/controller.dart'; import 'package:PiliPlus/pages/search/widgets/search_text.dart'; diff --git a/lib/pages/live_room/contribution_rank/controller.dart b/lib/pages/live_room/contribution_rank/controller.dart new file mode 100644 index 000000000..654e201b2 --- /dev/null +++ b/lib/pages/live_room/contribution_rank/controller.dart @@ -0,0 +1,45 @@ +import 'package:PiliPlus/http/live.dart'; +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/live/live_contribution_rank_type.dart'; +import 'package:PiliPlus/models_new/live/live_contribution_rank/data.dart'; +import 'package:PiliPlus/models_new/live/live_contribution_rank/item.dart'; +import 'package:PiliPlus/pages/common/common_list_controller.dart'; + +class ContributionRankController + extends + CommonListController< + LiveContributionRankData, + LiveContributionRankItem + > { + final Object ruid; + final Object roomId; + final LiveContributionRankType type; + + ContributionRankController({ + required this.ruid, + required this.roomId, + required this.type, + }); + + @override + void onInit() { + super.onInit(); + queryData(); + } + + @override + List? getDataList( + LiveContributionRankData response, + ) { + return response.item; + } + + @override + Future> customGetData() => + LiveHttp.liveContributionRank( + ruid: ruid, + roomId: roomId, + page: page, + type: type, + ); +} diff --git a/lib/pages/live_room/contribution_rank/view.dart b/lib/pages/live_room/contribution_rank/view.dart new file mode 100644 index 000000000..289d5f36c --- /dev/null +++ b/lib/pages/live_room/contribution_rank/view.dart @@ -0,0 +1,248 @@ +import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; +import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; +import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; +import 'package:PiliPlus/common/widgets/pendant_avatar.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; +import 'package:PiliPlus/common/widgets/view_sliver_safe_area.dart'; +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/live/live_contribution_rank_type.dart'; +import 'package:PiliPlus/models_new/live/live_contribution_rank/item.dart'; +import 'package:PiliPlus/models_new/live/live_contribution_rank/medal_info.dart'; +import 'package:PiliPlus/pages/live_room/contribution_rank/controller.dart'; +import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class ContributionRankPanel extends StatefulWidget { + const ContributionRankPanel({ + super.key, + required this.ruid, + required this.roomId, + }); + + final Object ruid; + final Object roomId; + + @override + State createState() => _ContributionRankPanelState(); +} + +class _ContributionRankPanelState extends State + with SingleTickerProviderStateMixin { + late final TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController( + length: LiveContributionRankType.values.length, + vsync: this, + ); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + SizedBox( + height: 45, + child: TabBar( + controller: _tabController, + tabs: LiveContributionRankType.values + .map((e) => Tab(text: e.title)) + .toList(), + dividerColor: Theme.of( + context, + ).colorScheme.outline.withValues(alpha: 0.3), + onTap: (index) { + if (!_tabController.indexIsChanging) { + Get.find( + tag: + '${widget.roomId}${LiveContributionRankType.values[index].name}', + ).scrollController.animToTop(); + } + }, + ), + ), + Expanded( + child: tabBarView( + controller: _tabController, + children: LiveContributionRankType.values + .map( + (e) => _ContributionRankType( + ruid: widget.ruid, + roomId: widget.roomId, + type: e, + ), + ) + .toList(), + ), + ), + ], + ); + } +} + +class _ContributionRankType extends StatefulWidget { + const _ContributionRankType({ + required this.ruid, + required this.roomId, + required this.type, + }); + + final Object ruid; + final Object roomId; + final LiveContributionRankType type; + + @override + State<_ContributionRankType> createState() => _ContributionRankTypeState(); +} + +class _ContributionRankTypeState extends State<_ContributionRankType> + with AutomaticKeepAliveClientMixin { + late final _controller = Get.put( + ContributionRankController( + ruid: widget.ruid, + roomId: widget.roomId, + type: widget.type, + ), + tag: '${widget.roomId}${widget.type.name}', + ); + + @override + Widget build(BuildContext context) { + super.build(context); + final showScore = widget.type == .online_rank; + return Material( + type: .transparency, + child: refreshIndicator( + onRefresh: _controller.onRefresh, + child: CustomScrollView( + controller: _controller.scrollController, + slivers: [ + ViewSliverSafeArea( + sliver: Obx( + () => _buildBody(showScore, _controller.loadingState.value), + ), + ), + ], + ), + ), + ); + } + + Widget _buildBody( + bool showScore, + LoadingState?> state, + ) { + return switch (state) { + Loading() => linearLoading, + Success(:final response) => + response != null && response.isNotEmpty + ? SliverFixedExtentList.builder( + itemCount: response.length, + itemBuilder: (context, index) { + final item = response[index]; + return _Item( + index: index, + item: item, + showScore: showScore, + ); + }, + itemExtent: 60, + ) + : HttpError(onReload: _controller.onReload), + Error(:final errMsg) => HttpError( + errMsg: errMsg, + onReload: _controller.onReload, + ), + }; + } + + @override + bool get wantKeepAlive => true; +} + +class _Item extends StatelessWidget { + const _Item({ + required this.index, + required this.item, + required this.showScore, + }); + + final int index; + final bool showScore; + final LiveContributionRankItem item; + + @override + Widget build(BuildContext context) { + late final colorScheme = ColorScheme.of(context); + return InkWell( + onTap: () => Get.toNamed('/member?mid=${item.uid}'), + child: Padding( + padding: const .only(left: 10, top: 9, bottom: 8, right: 16), + child: Row( + spacing: 10, + children: [ + SizedBox( + width: 32, + child: Center( + child: Text( + '${index + 1}', + textAlign: .center, + textScaler: .noScaling, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Utils.index2Color(index, colorScheme.outline), + fontSize: 16, + fontStyle: FontStyle.italic, + ), + ), + ), + ), + PendantAvatar( + avatar: item.face, + size: 42, + ), + Expanded( + child: Column( + spacing: 3, + crossAxisAlignment: .start, + children: [ + Text(item.name!), + Row( + children: [ + if (item.medalInfo case MedalInfo( + :final medalName, + :final level, + )) + Text( + '$medalName$level', + style: TextStyle( + fontSize: 12, + color: colorScheme.onSurfaceVariant, + ), + ), + ], + ), + ], + ), + ), + if (showScore) + Text( + item.score.toString(), + style: TextStyle(color: colorScheme.outline), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index 9266c3b55..d39d63714 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -15,6 +15,7 @@ import 'package:PiliPlus/models_new/live/live_room_play_info/codec.dart'; import 'package:PiliPlus/models_new/live/live_superchat/item.dart'; import 'package:PiliPlus/pages/common/publish/publish_route.dart'; import 'package:PiliPlus/pages/danmaku/danmaku_model.dart'; +import 'package:PiliPlus/pages/live_room/contribution_rank/view.dart'; import 'package:PiliPlus/pages/live_room/send_danmaku/view.dart'; import 'package:PiliPlus/pages/video/widgets/header_control.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; @@ -26,6 +27,7 @@ import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/danmaku_utils.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension/iterable_ext.dart'; +import 'package:PiliPlus/utils/extension/size_ext.dart'; import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/platform_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; @@ -43,6 +45,7 @@ class LiveRoomController extends GetxController { final String heroTag; int roomId = Get.arguments; + int? ruid; DanmakuController? danmakuController; PlPlayerController plPlayerController = PlPlayerController.getInstance( isLive: true, @@ -109,7 +112,6 @@ class LiveRoomController extends GetxController { late final bool isLogin; late final int mid; - late final int mainMid = Accounts.main.mid; String? videoUrl; bool? isPlaying; @@ -123,18 +125,40 @@ class LiveRoomController extends GetxController { final RxString title = ''.obs; final RxnString onlineCount = RxnString(); - Widget get onlineWidget => Obx(() { - if (onlineCount.value case final onlineCount?) { - return Text( - '高能观众($onlineCount)', - style: const TextStyle( - fontSize: 12, - color: Colors.white, + Widget get onlineWidget => GestureDetector( + onTap: _showRank, + child: Obx(() { + if (onlineCount.value case final onlineCount?) { + return Text( + '高能观众($onlineCount)', + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ); + } + return const SizedBox.shrink(); + }), + ); + + void _showRank() { + if (ruid case final ruid?) { + final heightFactor = + PlatformUtils.isMobile && !Get.mediaQuery.size.isPortrait ? 1.0 : 0.7; + showModalBottomSheet( + context: Get.context!, + useSafeArea: true, + clipBehavior: .hardEdge, + isScrollControlled: true, + constraints: const BoxConstraints(maxWidth: 450), + builder: (context) => FractionallySizedBox( + widthFactor: 1.0, + heightFactor: heightFactor, + child: ContributionRankPanel(ruid: ruid, roomId: roomId), ), ); } - return const SizedBox.shrink(); - }); + } final RxnString watchedShow = RxnString(); Widget get watchedWidget => Obx(() { @@ -207,6 +231,7 @@ class LiveRoomController extends GetxController { _showDialog('无法获取播放地址'); return; } + ruid = data.uid; if (data.roomId != null) { roomId = data.roomId!; } @@ -439,7 +464,7 @@ class LiveRoomController extends GetxController { : DmUtils.decimalToColor(extra['color']), type: DmUtils.getPosition(extra['mode']), // extra['send_from_me'] is invalid - selfSend: uid == mainMid, + selfSend: isLogin && uid == mid, extra: LiveDanmaku( id: extra['id_str'], mid: uid, diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index c3674d7f1..36df36b84 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -8,9 +8,11 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/models/common/image_type.dart'; +import 'package:PiliPlus/models/common/live/live_contribution_rank_type.dart'; import 'package:PiliPlus/models_new/live/live_room_info_h5/data.dart'; import 'package:PiliPlus/models_new/live/live_superchat/item.dart'; import 'package:PiliPlus/pages/danmaku/danmaku_model.dart'; +import 'package:PiliPlus/pages/live_room/contribution_rank/controller.dart'; import 'package:PiliPlus/pages/live_room/controller.dart'; import 'package:PiliPlus/pages/live_room/superchat/superchat_card.dart'; import 'package:PiliPlus/pages/live_room/superchat/superchat_panel.dart'; @@ -155,6 +157,11 @@ class _LiveRoomPageState extends State ..removeStatusLister(playerListener) ..dispose(); PageUtils.routeObserver.unsubscribe(this); + for (final e in LiveContributionRankType.values) { + Get.delete( + tag: '${_liveRoomController.roomId}${e.name}', + ); + } super.dispose(); } diff --git a/lib/pages/live_search/child/controller.dart b/lib/pages/live_search/child/controller.dart index 7801359b3..dcf800cef 100644 --- a/lib/pages/live_search/child/controller.dart +++ b/lib/pages/live_search/child/controller.dart @@ -1,6 +1,6 @@ import 'package:PiliPlus/http/live.dart'; import 'package:PiliPlus/http/loading_state.dart'; -import 'package:PiliPlus/models/common/live_search_type.dart'; +import 'package:PiliPlus/models/common/live/live_search_type.dart'; import 'package:PiliPlus/models_new/live/live_search/data.dart'; import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:PiliPlus/pages/live_search/controller.dart'; diff --git a/lib/pages/live_search/child/view.dart b/lib/pages/live_search/child/view.dart index 00569100d..2d26b8eb9 100644 --- a/lib/pages/live_search/child/view.dart +++ b/lib/pages/live_search/child/view.dart @@ -4,7 +4,7 @@ import 'package:PiliPlus/common/skeleton/video_card_v.dart'; import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/http/loading_state.dart'; -import 'package:PiliPlus/models/common/live_search_type.dart'; +import 'package:PiliPlus/models/common/live/live_search_type.dart'; import 'package:PiliPlus/pages/live_search/child/controller.dart'; import 'package:PiliPlus/pages/live_search/widgets/live_search_room.dart'; import 'package:PiliPlus/pages/live_search/widgets/live_search_user.dart'; diff --git a/lib/pages/live_search/controller.dart b/lib/pages/live_search/controller.dart index e9400e331..21abb667c 100644 --- a/lib/pages/live_search/controller.dart +++ b/lib/pages/live_search/controller.dart @@ -1,4 +1,4 @@ -import 'package:PiliPlus/models/common/live_search_type.dart'; +import 'package:PiliPlus/models/common/live/live_search_type.dart'; import 'package:PiliPlus/pages/live_search/child/controller.dart'; import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart'; import 'package:PiliPlus/utils/id_utils.dart'; diff --git a/lib/pages/live_search/view.dart b/lib/pages/live_search/view.dart index 52e9c43e7..0ff89aff1 100644 --- a/lib/pages/live_search/view.dart +++ b/lib/pages/live_search/view.dart @@ -1,6 +1,6 @@ import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/view_safe_area.dart'; -import 'package:PiliPlus/models/common/live_search_type.dart'; +import 'package:PiliPlus/models/common/live/live_search_type.dart'; import 'package:PiliPlus/pages/live_search/child/view.dart'; import 'package:PiliPlus/pages/live_search/controller.dart'; import 'package:PiliPlus/utils/utils.dart'; diff --git a/lib/pages/member/widget/user_info_card.dart b/lib/pages/member/widget/user_info_card.dart index e0e9077ca..98a6ca8e4 100644 --- a/lib/pages/member/widget/user_info_card.dart +++ b/lib/pages/member/widget/user_info_card.dart @@ -115,10 +115,10 @@ class UserInfoCard extends StatelessWidget { ? images.imgUrl : images.nightImgurl) .http2https; - return Hero( - tag: imgUrl, - child: GestureDetector( - onTap: () => PageUtils.imageView(imgList: [SourceModel(url: imgUrl)]), + return GestureDetector( + onTap: () => PageUtils.imageView(imgList: [SourceModel(url: imgUrl)]), + child: Hero( + tag: imgUrl, child: CachedNetworkImage( imageUrl: ImageUtils.thumbnailUrl(imgUrl), width: double.infinity, diff --git a/lib/pages/search_trending/view.dart b/lib/pages/search_trending/view.dart index da0957b08..62897b399 100644 --- a/lib/pages/search_trending/view.dart +++ b/lib/pages/search_trending/view.dart @@ -11,6 +11,7 @@ import 'package:PiliPlus/utils/extension/context_ext.dart'; import 'package:PiliPlus/utils/extension/get_ext.dart'; import 'package:PiliPlus/utils/extension/size_ext.dart'; import 'package:PiliPlus/utils/image_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart' hide ListTile; @@ -177,12 +178,10 @@ class _SearchTrendingPageState extends State { '${index + 1 - _controller.topCount}', style: TextStyle( fontWeight: FontWeight.bold, - color: switch (index - _controller.topCount) { - 0 => const Color(0xFFfdad13), - 1 => const Color(0xFF8aace1), - 2 => const Color(0xFFdfa777), - _ => theme.colorScheme.outline, - }, + color: Utils.index2Color( + index - _controller.topCount, + theme.colorScheme.outline, + ), fontSize: 17, fontStyle: FontStyle.italic, ), diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index d4c050a11..25c8bfb78 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -21,6 +21,13 @@ abstract final class Utils { static const jsonEncoder = JsonEncoder.withIndent(' '); + static Color index2Color(int index, Color color) => switch (index) { + 0 => const Color(0xFFfdad13), + 1 => const Color(0xFF8aace1), + 2 => const Color(0xFFdfa777), + _ => color, + }; + static String themeUrl(bool isDark) => 'native.theme=${isDark ? 2 : 1}&night=${isDark ? 1 : 0}';