diff --git a/lib/common/widgets/loading_widget/http_error.dart b/lib/common/widgets/loading_widget/http_error.dart index f726b68e5..b527110cd 100644 --- a/lib/common/widgets/loading_widget/http_error.dart +++ b/lib/common/widgets/loading_widget/http_error.dart @@ -19,14 +19,8 @@ class HttpError extends StatelessWidget { @override Widget build(BuildContext context) { - return isSliver - ? SliverToBoxAdapter(child: content(context)) - : SizedBox(width: double.infinity, child: content(context)); - } - - Widget content(BuildContext context) { final theme = Theme.of(context); - return Column( + final child = Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, @@ -63,5 +57,9 @@ class HttpError extends StatelessWidget { SizedBox(height: 40 + MediaQuery.viewPaddingOf(context).bottom), ], ); + + return isSliver + ? SliverToBoxAdapter(child: child) + : SizedBox(width: double.infinity, child: child); } } diff --git a/lib/common/widgets/loading_widget/loading_widget.dart b/lib/common/widgets/loading_widget/loading_widget.dart index ce9ec642e..9be42fa19 100644 --- a/lib/common/widgets/loading_widget/loading_widget.dart +++ b/lib/common/widgets/loading_widget/loading_widget.dart @@ -1,17 +1,14 @@ import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:flutter/material.dart'; -Widget get loadingWidget => const Center(child: CircularProgressIndicator()); +const Widget circularLoading = Center(child: CircularProgressIndicator()); -Widget get linearLoading => - const SliverToBoxAdapter(child: LinearProgressIndicator()); - -Widget errorWidget({String? errMsg, VoidCallback? onReload}) => HttpError( - isSliver: false, - errMsg: errMsg, - onReload: onReload, +const Widget linearLoading = SliverToBoxAdapter( + child: LinearProgressIndicator(), ); +const Widget scrollableError = CustomScrollView(slivers: [HttpError()]); + Widget scrollErrorWidget({ String? errMsg, VoidCallback? onReload, diff --git a/lib/models/dynamics/article_content_model.dart b/lib/models/dynamics/article_content_model.dart index 7b7d6ad18..ba9db4115 100644 --- a/lib/models/dynamics/article_content_model.dart +++ b/lib/models/dynamics/article_content_model.dart @@ -340,6 +340,7 @@ class Common { int? style; String? subType; String? title; + String? titlePrefix; Common.fromJson(Map json) { cover = json['cover']; @@ -352,6 +353,7 @@ class Common { style = json['style']; subType = json['sub_type']; title = json['title']; + titlePrefix = json['title_prefix']; } } diff --git a/lib/pages/danmaku_block/view.dart b/lib/pages/danmaku_block/view.dart index b0ea54e1a..8adc3d119 100644 --- a/lib/pages/danmaku_block/view.dart +++ b/lib/pages/danmaku_block/view.dart @@ -82,7 +82,7 @@ class _DanmakuBlockPageState extends State { Widget tabViewBuilder(final int tabIndex, List list) { if (list.isEmpty) { - return scrollErrorWidget(); + return scrollableError; } return ListView.builder( itemCount: list.length, diff --git a/lib/pages/dynamics/widgets/module_panel.dart b/lib/pages/dynamics/widgets/module_panel.dart index cfeaabd71..5ca4005f5 100644 --- a/lib/pages/dynamics/widgets/module_panel.dart +++ b/lib/pages/dynamics/widgets/module_panel.dart @@ -153,13 +153,12 @@ Widget module( spacing: 2, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (common.title?.isNotEmpty ?? false) - Text( - common.title!, - style: TextStyle(color: theme.colorScheme.primary), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), + Text( + '${common.titlePrefix ?? ''}${common.title ?? ''}', + style: TextStyle(color: theme.colorScheme.primary), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), if (common.desc?.isNotEmpty ?? false) Text( common.desc!, diff --git a/lib/pages/dynamics_mention/view.dart b/lib/pages/dynamics_mention/view.dart index 219659688..3bd8f679a 100644 --- a/lib/pages/dynamics_mention/view.dart +++ b/lib/pages/dynamics_mention/view.dart @@ -234,8 +234,8 @@ class _DynMentionPanelState LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => SliverPadding( - padding: const EdgeInsets.only(top: 8), + Loading() => const SliverPadding( + padding: EdgeInsets.only(top: 8), sliver: linearLoading, ), Success?>(:final response) => diff --git a/lib/pages/dynamics_select_topic/view.dart b/lib/pages/dynamics_select_topic/view.dart index 7a7ed7c0d..240a7d9c8 100644 --- a/lib/pages/dynamics_select_topic/view.dart +++ b/lib/pages/dynamics_select_topic/view.dart @@ -188,7 +188,7 @@ class _SelectTopicPanelState LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success?>(:final response) => response != null && response.isNotEmpty ? ListView.builder( diff --git a/lib/pages/emote/view.dart b/lib/pages/emote/view.dart index 3be2ff6aa..9a4061d25 100644 --- a/lib/pages/emote/view.dart +++ b/lib/pages/emote/view.dart @@ -50,7 +50,7 @@ class _EmotePanelState extends State Get.currentRoute.startsWith('/whisperDetail') ? 8 : 2, ); return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => response != null && response.isNotEmpty ? Column( diff --git a/lib/pages/fav/topic/view.dart b/lib/pages/fav/topic/view.dart index 0a35f2c33..0941615e3 100644 --- a/lib/pages/fav/topic/view.dart +++ b/lib/pages/fav/topic/view.dart @@ -2,6 +2,8 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; 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' + show circularLoading; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models_new/fav/fav_topic/topic_item.dart'; import 'package:PiliPlus/pages/fav/topic/controller.dart'; @@ -66,9 +68,7 @@ class _FavTopicPageState extends State Loading() => const SliverToBoxAdapter( child: SizedBox( height: 125, - child: Center( - child: CircularProgressIndicator(), - ), + child: circularLoading, ), ), Success(:final response) => diff --git a/lib/pages/fav_create/view.dart b/lib/pages/fav_create/view.dart index 9c3569a99..c2febfccc 100644 --- a/lib/pages/fav_create/view.dart +++ b/lib/pages/fav_create/view.dart @@ -107,7 +107,7 @@ class _CreateFavPageState extends State { ? _buildBody(theme) : _errMsg?.isNotEmpty == true ? scrollErrorWidget(errMsg: _errMsg, onReload: _getFolderInfo) - : const Center(child: CircularProgressIndicator()) + : circularLoading : _buildBody(theme), ); } diff --git a/lib/pages/fav_panel/view.dart b/lib/pages/fav_panel/view.dart index ea3b91e94..605a17352 100644 --- a/lib/pages/fav_panel/view.dart +++ b/lib/pages/fav_panel/view.dart @@ -41,7 +41,7 @@ class _FavPanelState extends State { Widget get _buildBody { late final list = widget.ctr.favFolderData.value.list!; return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success() => ListView.builder( controller: widget.scrollController, itemCount: list.length, diff --git a/lib/pages/follow/view.dart b/lib/pages/follow/view.dart index eacb2e9d6..2086c8b3c 100644 --- a/lib/pages/follow/view.dart +++ b/lib/pages/follow/view.dart @@ -109,7 +109,7 @@ class _FollowPageState extends State { Widget _buildBody(LoadingState loadingState) { return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success() => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/group_panel/view.dart b/lib/pages/group_panel/view.dart index 69173e8a6..e4a8dab70 100644 --- a/lib/pages/group_panel/view.dart +++ b/lib/pages/group_panel/view.dart @@ -68,7 +68,7 @@ class _GroupPanelState extends State { Widget get _buildBody { return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => ListView.builder( controller: widget.scrollController, itemCount: response.length, diff --git a/lib/pages/live_dm_block/view.dart b/lib/pages/live_dm_block/view.dart index 7f190168c..fbc501722 100644 --- a/lib/pages/live_dm_block/view.dart +++ b/lib/pages/live_dm_block/view.dart @@ -157,7 +157,7 @@ class _LiveDmBlockPageState extends State { Widget _buildKeyword(List list) { if (list.isEmpty) { - return scrollErrorWidget(); + return scrollableError; } return SingleChildScrollView( padding: EdgeInsets.only( diff --git a/lib/pages/live_emote/view.dart b/lib/pages/live_emote/view.dart index e5f2bd83f..bf9c4521e 100644 --- a/lib/pages/live_emote/view.dart +++ b/lib/pages/live_emote/view.dart @@ -57,7 +57,7 @@ class _LiveEmotePanelState extends State 2, ); return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => response != null && response.isNotEmpty ? Column( diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index a83112859..1cd33a509 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'dart:ui'; import 'package:PiliPlus/common/constants.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/scroll_physics.dart'; import 'package:PiliPlus/http/loading_state.dart'; @@ -96,15 +97,12 @@ class _LoginPageState extends State { ), RepaintBoundary( key: globalKey, - child: Obx(() { - return switch (_loginPageCtr.codeInfo.value) { - Loading() => Container( + child: Obx( + () => switch (_loginPageCtr.codeInfo.value) { + Loading() => const SizedBox( height: 200, width: 200, - alignment: Alignment.center, - child: const CircularProgressIndicator( - semanticsLabel: '二维码加载中', - ), + child: circularLoading, ), Success(:final response) => Container( width: 200, @@ -120,12 +118,13 @@ class _LoginPageState extends State { ), ), ), - Error(:final errMsg) => errorWidget( + Error(:final errMsg) => HttpError( + isSliver: false, errMsg: errMsg, onReload: _loginPageCtr.refreshQRCode, ), - }; - }), + }, + ), ), const SizedBox(height: 10), Obx( diff --git a/lib/pages/member/view.dart b/lib/pages/member/view.dart index cadd6822f..df99ee141 100644 --- a/lib/pages/member/view.dart +++ b/lib/pages/member/view.dart @@ -5,7 +5,6 @@ import 'package:PiliPlus/common/widgets/dynamic_sliver_app_bar/dynamic_sliver_ap 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'; -import 'package:PiliPlus/models_new/space/space/data.dart'; import 'package:PiliPlus/pages/coin_log/controller.dart'; import 'package:PiliPlus/pages/exp_log/controller.dart'; import 'package:PiliPlus/pages/log_table/view.dart'; @@ -68,48 +67,74 @@ class _MemberPageState extends State { return Material( color: theme.surface, child: Obx( - () { - if (_userController.loadingState.value.isSuccess) { - return ExtendedNestedScrollView( - key: _userController.key, - onlyOneScrollInBody: true, - pinnedHeaderSliverHeightBuilder: () => - kToolbarHeight + MediaQuery.viewPaddingOf(context).top, - headerSliverBuilder: (context, innerBoxIsScrolled) { + () => switch (_userController.loadingState.value) { + Loading() => circularLoading, + Success(:final response) => ExtendedNestedScrollView( + key: _userController.key, + onlyOneScrollInBody: true, + pinnedHeaderSliverHeightBuilder: () => + kToolbarHeight + MediaQuery.viewPaddingOf(context).top, + headerSliverBuilder: (context, innerBoxIsScrolled) { + if (response != null) { return [ - _buildUserInfo(theme, _userController.loadingState.value), - ]; - }, - body: _userController.tab2?.isNotEmpty == true - ? Padding( - padding: EdgeInsets.only( - left: padding.left, - right: padding.right, + DynamicSliverAppBar.medium( + actions: _actions(theme), + title: Text(_userController.username ?? ''), + flexibleSpace: Obx( + () => UserInfoCard( + isOwner: + _userController.mid == _userController.account.mid, + relation: _userController.relation.value, + card: response.card!, + images: response.images!, + onFollow: () => _userController.onFollow(context), + live: _userController.live, + silence: _userController.silence, + headerControllerBuilder: getHeaderController, ), - child: Column( - children: [ - if ((_userController.tab2?.length ?? 0) > 1) - SizedBox( - height: 45, - child: TabBar( - controller: _userController.tabController, - tabs: _userController.tabs, - onTap: _userController.onTapTab, - dividerColor: theme.outline.withValues( - alpha: 0.2, - ), + ), + ), + ]; + } + return [ + SliverAppBar( + pinned: true, + actions: _actions(theme), + title: GestureDetector( + onTap: _userController.onReload, + behavior: HitTestBehavior.opaque, + child: Text(_userController.username ?? ''), + ), + ), + ]; + }, + body: _userController.tab2?.isNotEmpty == true + ? Padding( + padding: .only(left: padding.left, right: padding.right), + child: Column( + children: [ + if ((_userController.tab2?.length ?? 0) > 1) + SizedBox( + height: 45, + child: TabBar( + controller: _userController.tabController, + tabs: _userController.tabs, + onTap: _userController.onTapTab, + dividerColor: theme.outline.withValues( + alpha: 0.2, ), ), - Expanded(child: _buildBody), - ], - ), - ) - : const Center(child: Text('EMPTY')), - ); - } - return Center( - child: _buildUserInfo(theme, _userController.loadingState.value), - ); + ), + Expanded(child: _buildBody), + ], + ), + ) + : scrollableError, + ), + Error(:final errMsg) => scrollErrorWidget( + errMsg: errMsg, + onReload: _userController.onReload, + ), }, ), ); @@ -346,47 +371,4 @@ class _MemberPageState extends State { }; }).toList(), ); - - Widget _buildUserInfo( - ColorScheme theme, - LoadingState userState, - ) { - switch (userState) { - case Loading(): - return const CircularProgressIndicator(); - case Success(:final response): - if (response != null) { - return DynamicSliverAppBar.medium( - actions: _actions(theme), - title: Text(_userController.username ?? ''), - flexibleSpace: Obx( - () => UserInfoCard( - isOwner: _userController.mid == _userController.account.mid, - relation: _userController.relation.value, - card: response.card!, - images: response.images!, - onFollow: () => _userController.onFollow(context), - live: _userController.live, - silence: _userController.silence, - headerControllerBuilder: getHeaderController, - ), - ), - ); - } - return SliverAppBar( - pinned: true, - actions: _actions(theme), - title: GestureDetector( - onTap: _userController.onReload, - behavior: HitTestBehavior.opaque, - child: Text(_userController.username ?? ''), - ), - ); - case Error(:final errMsg): - return scrollErrorWidget( - errMsg: errMsg, - onReload: _userController.onReload, - ); - } - } } diff --git a/lib/pages/member_contribute/view.dart b/lib/pages/member_contribute/view.dart index 06a6443a6..818c6e5a6 100644 --- a/lib/pages/member_contribute/view.dart +++ b/lib/pages/member_contribute/view.dart @@ -93,7 +93,7 @@ class _MemberContributeState extends State ) : _controller.items?.isNotEmpty == true ? _getPageFromType(_controller.items!.first) - : scrollErrorWidget(); + : scrollableError; } Widget _getPageFromType(SpaceTab2Item item) { diff --git a/lib/pages/member_home/view.dart b/lib/pages/member_home/view.dart index 0e5533b8d..30e86ff87 100644 --- a/lib/pages/member_home/view.dart +++ b/lib/pages/member_home/view.dart @@ -73,7 +73,7 @@ class _MemberHomeState extends State final isOwner = setting != null; final color = Theme.of(context).colorScheme.outline; return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(response: final res) => res != null ? CustomScrollView( @@ -257,7 +257,7 @@ class _MemberHomeState extends State ), ], ) - : scrollErrorWidget(), + : scrollableError, Error(:final errMsg) => scrollErrorWidget(errMsg: errMsg), }; } diff --git a/lib/pages/member_profile/view.dart b/lib/pages/member_profile/view.dart index ef508c5b2..cb814634a 100644 --- a/lib/pages/member_profile/view.dart +++ b/lib/pages/member_profile/view.dart @@ -127,7 +127,7 @@ class _EditProfilePageState extends State { ); return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => ListView( padding: EdgeInsets.only( bottom: MediaQuery.viewPaddingOf(context).bottom + 25, diff --git a/lib/pages/pgc/view.dart b/lib/pages/pgc/view.dart index b1dfae1e3..e6d14831b 100644 --- a/lib/pages/pgc/view.dart +++ b/lib/pages/pgc/view.dart @@ -83,7 +83,7 @@ class _PgcPageState extends State with AutomaticKeepAliveClientMixin { ThemeData theme, LoadingState?> loadingState, ) => switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => response != null && response.isNotEmpty ? Builder( @@ -397,7 +397,7 @@ class _PgcPageState extends State with AutomaticKeepAliveClientMixin { Widget _buildFollowBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => response != null && response.isNotEmpty ? ListView.builder( diff --git a/lib/pages/pgc_index/view.dart b/lib/pages/pgc_index/view.dart index 31bffe0ae..7ddc656d8 100644 --- a/lib/pages/pgc_index/view.dart +++ b/lib/pages/pgc_index/view.dart @@ -58,7 +58,7 @@ class _PgcIndexPageState extends State ) { final padding = MediaQuery.viewPaddingOf(context); return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => Builder( builder: (context) { int count = diff --git a/lib/pages/setting/pages/logs.dart b/lib/pages/setting/pages/logs.dart index 5e92ca894..040b26621 100644 --- a/lib/pages/setting/pages/logs.dart +++ b/lib/pages/setting/pages/logs.dart @@ -184,7 +184,7 @@ class _LogsPageState extends State { ], ), ) - : scrollErrorWidget(), + : scrollableError, ); } } diff --git a/lib/pages/video/member/view.dart b/lib/pages/video/member/view.dart index ab8276cef..8b4fb21c9 100644 --- a/lib/pages/video/member/view.dart +++ b/lib/pages/video/member/view.dart @@ -81,7 +81,7 @@ class _HorizontalMemberPageState extends State { Widget _buildUserPage(ThemeData theme, LoadingState userState) { return switch (userState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => Column( children: [ _buildUserInfo(theme, response), diff --git a/lib/pages/video/post_panel/view.dart b/lib/pages/video/post_panel/view.dart index 5b18773cf..b2b6c6153 100644 --- a/lib/pages/video/post_panel/view.dart +++ b/lib/pages/video/post_panel/view.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'package:PiliPlus/common/widgets/button/icon_button.dart'; -import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; +import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/pair.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/sponsor_block.dart'; @@ -249,7 +249,7 @@ class _PostPanelState extends State @override Widget buildList(ThemeData theme) { if (list.isEmpty) { - return errorWidget(); + return const HttpError(isSliver: false); } final bottom = MediaQuery.viewPaddingOf(context).bottom; Widget child = ListView.builder( diff --git a/lib/pages/whisper_block/view.dart b/lib/pages/whisper_block/view.dart index 441e71a27..4bda0332e 100644 --- a/lib/pages/whisper_block/view.dart +++ b/lib/pages/whisper_block/view.dart @@ -37,7 +37,7 @@ class _WhisperBlockPageState extends State { LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => response != null && response.isNotEmpty ? Column( diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index ff57111ae..162f7e3c8 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -151,7 +151,7 @@ class _WhisperDetailPageState Widget _buildBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => loadingWidget, + Loading() => circularLoading, Success(:final response) => response != null && response.isNotEmpty ? ChatListView.separated(