mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: safearea
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -43,10 +43,10 @@ class DynamicSliverAppBar extends StatefulWidget {
|
||||
this.forceMaterialTransparency = false,
|
||||
this.clipBehavior,
|
||||
this.appBarClipper,
|
||||
this.hasTabBar = false,
|
||||
this.callback,
|
||||
});
|
||||
|
||||
final bool hasTabBar;
|
||||
final ValueChanged<double>? callback;
|
||||
final Widget? flexibleSpace;
|
||||
final Widget? leading;
|
||||
final bool automaticallyImplyLeading;
|
||||
@@ -113,6 +113,7 @@ class _DynamicSliverAppBarState extends State<DynamicSliverAppBar> {
|
||||
_height = (_childKey.currentContext!.findRenderObject()! as RenderBox)
|
||||
.size
|
||||
.height;
|
||||
widget.callback?.call(_height);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -166,7 +167,7 @@ class _DynamicSliverAppBarState extends State<DynamicSliverAppBar> {
|
||||
onStretchTrigger: widget.onStretchTrigger,
|
||||
shape: widget.shape,
|
||||
toolbarHeight: widget.toolbarHeight,
|
||||
expandedHeight: _height + (widget.hasTabBar ? 48 : 0),
|
||||
expandedHeight: _height,
|
||||
leadingWidth: widget.leadingWidth,
|
||||
toolbarTextStyle: widget.toolbarTextStyle,
|
||||
titleTextStyle: widget.titleTextStyle,
|
||||
|
||||
@@ -51,7 +51,9 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
int count = (data.order?.isNotEmpty == true ? 1 : 0) +
|
||||
(data.filter?.length ?? 0);
|
||||
if (count == 0) return const SizedBox.shrink();
|
||||
return CustomScrollView(
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
if (widget.indexType != null)
|
||||
SliverToBoxAdapter(child: const SizedBox(height: 12)),
|
||||
@@ -75,6 +77,7 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
sliver: Obx(() => _buildList(_ctr.loadingState.value)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
Error() => scrollErrorWidget(
|
||||
|
||||
@@ -248,10 +248,14 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
length: types.length,
|
||||
child: Column(
|
||||
children: [
|
||||
TabBar(
|
||||
SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: TabBar(
|
||||
tabs: titles
|
||||
.map((title) => Tab(text: title))
|
||||
.toList()),
|
||||
),
|
||||
Expanded(
|
||||
child: tabBarView(
|
||||
children: types
|
||||
|
||||
@@ -48,13 +48,17 @@ abstract class CommonSearchPageState<S extends CommonSearchPage, R, T>
|
||||
onSubmitted: (value) => controller.onRefresh(),
|
||||
),
|
||||
),
|
||||
body: CustomScrollView(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
controller: controller.scrollController,
|
||||
slivers: [
|
||||
Obx(() => _buildBody(controller.loadingState.value)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,10 +103,6 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
super.initState();
|
||||
// floor 1原创 2转发
|
||||
init();
|
||||
// if (action == 'comment') {
|
||||
// _visibleTitle = true;
|
||||
// _titleStreamC.add(true);
|
||||
// }
|
||||
|
||||
_fabAnimationCtr = AnimationController(
|
||||
vsync: this,
|
||||
@@ -340,7 +336,10 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
]
|
||||
: null,
|
||||
),
|
||||
body: context.orientation == Orientation.portrait
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: context.orientation == Orientation.portrait
|
||||
? refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _dynamicDetailController.onRefresh();
|
||||
@@ -348,6 +347,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
child: _buildBody(context.orientation),
|
||||
)
|
||||
: _buildBody(context.orientation),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,9 @@ class _FansPageState extends State<FansPage> {
|
||||
_fansController.isOwner.value ? '我的粉丝' : '${_fansController.name}的粉丝',
|
||||
),
|
||||
),
|
||||
body: refreshIndicator(
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
child: refreshIndicator(
|
||||
onRefresh: () async => await _fansController.onRefresh(),
|
||||
child: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
@@ -47,6 +49,7 @@ class _FansPageState extends State<FansPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,11 @@ class _FavFolderSortPageState extends State<FavFolderSortPage> {
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
),
|
||||
body: _buildBody,
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: _buildBody,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,13 @@ class _FavPageState extends State<FavPage> with SingleTickerProviderStateMixin {
|
||||
),
|
||||
body: tabBarView(
|
||||
controller: _tabController,
|
||||
children: _FavType.values.map((item) => item.page).toList(),
|
||||
children: _FavType.values
|
||||
.map((item) => SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: item.page,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,11 @@ class _FavSortPageState extends State<FavSortPage> {
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
),
|
||||
body: _buildBody,
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: _buildBody,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,10 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
body: refreshIndicator(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _favDetailController.onRefresh();
|
||||
},
|
||||
@@ -91,7 +94,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
icon: const Icon(Icons.close_outlined),
|
||||
)
|
||||
: null,
|
||||
expandedHeight: 220 - MediaQuery.of(context).padding.top,
|
||||
expandedHeight: 200 - MediaQuery.of(context).padding.top,
|
||||
pinned: true,
|
||||
title: _favDetailController.enableMultiSelect.value
|
||||
? Text(
|
||||
@@ -202,9 +205,10 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
arguments: {
|
||||
'type': 0,
|
||||
'mediaId': int.parse(mediaId),
|
||||
'title': _favDetailController.item.value.title,
|
||||
'count':
|
||||
_favDetailController.item.value.mediaCount,
|
||||
'title':
|
||||
_favDetailController.item.value.title,
|
||||
'count': _favDetailController
|
||||
.item.value.mediaCount,
|
||||
'isOwner': _favDetailController.isOwner.value,
|
||||
},
|
||||
),
|
||||
@@ -222,8 +226,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
parameters: {'mediaId': mediaId},
|
||||
)?.then((res) {
|
||||
if (res is FavFolderItemData) {
|
||||
_favDetailController.item.value =
|
||||
res;
|
||||
_favDetailController
|
||||
.item.value = res;
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -238,7 +242,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
Future.delayed(
|
||||
const Duration(
|
||||
milliseconds: 200), () {
|
||||
_favDetailController.onReload();
|
||||
_favDetailController
|
||||
.onReload();
|
||||
});
|
||||
} else {
|
||||
SmartDialog.showToast(
|
||||
@@ -250,16 +255,18 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () {
|
||||
if (_favDetailController.loadingState
|
||||
if (_favDetailController
|
||||
.loadingState
|
||||
.value is Success &&
|
||||
((_favDetailController
|
||||
.loadingState
|
||||
.value as Success)
|
||||
.value
|
||||
as Success)
|
||||
.response as List?)
|
||||
?.isNotEmpty ==
|
||||
true) {
|
||||
if ((_favDetailController.item.value
|
||||
.mediaCount ??
|
||||
if ((_favDetailController.item
|
||||
.value.mediaCount ??
|
||||
0) >
|
||||
1000) {
|
||||
SmartDialog.showToast(
|
||||
@@ -344,13 +351,15 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
height: 110,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
_favDetailController.item.value.title ??
|
||||
_favDetailController
|
||||
.item.value.title ??
|
||||
'',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
@@ -415,12 +424,14 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(() => _buildBody(_favDetailController.loadingState.value)),
|
||||
Obx(() =>
|
||||
_buildBody(_favDetailController.loadingState.value)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,10 @@ class _FollowPageState extends State<FollowPage> {
|
||||
if (data['status']) {
|
||||
return Column(
|
||||
children: [
|
||||
TabBar(
|
||||
SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: TabBar(
|
||||
controller: _followController.tabController,
|
||||
isScrollable: true,
|
||||
tabAlignment: TabAlignment.start,
|
||||
@@ -86,6 +89,7 @@ class _FollowPageState extends State<FollowPage> {
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
|
||||
@@ -92,12 +92,12 @@ class _FollowListState extends State<FollowList> {
|
||||
}
|
||||
},
|
||||
)
|
||||
: errorWidget(
|
||||
: scrollErrorWidget(
|
||||
callback: () => widget.ctr.queryFollowings('init'),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return errorWidget(
|
||||
return scrollErrorWidget(
|
||||
errMsg: data['msg'],
|
||||
callback: () => widget.ctr.queryFollowings('init'),
|
||||
);
|
||||
|
||||
@@ -107,12 +107,12 @@ class _OwnerFollowListState extends State<OwnerFollowList>
|
||||
);
|
||||
},
|
||||
)
|
||||
: errorWidget(
|
||||
: scrollErrorWidget(
|
||||
callback: () => widget.ctr.queryFollowings('init'),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return errorWidget(
|
||||
return scrollErrorWidget(
|
||||
errMsg: data['msg'],
|
||||
callback: () => widget.ctr.queryFollowings('init'),
|
||||
);
|
||||
|
||||
@@ -182,7 +182,10 @@ class _HistoryPageState extends State<HistoryPage>
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TabBar(
|
||||
SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: TabBar(
|
||||
controller: _historyController.tabController,
|
||||
onTap: (index) {
|
||||
if (_historyController
|
||||
@@ -203,6 +206,7 @@ class _HistoryPageState extends State<HistoryPage>
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
@@ -229,7 +233,10 @@ class _HistoryPageState extends State<HistoryPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildPage => refreshIndicator(
|
||||
Widget get _buildPage => SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _historyController.onRefresh();
|
||||
},
|
||||
@@ -240,6 +247,7 @@ class _HistoryPageState extends State<HistoryPage>
|
||||
Obx(() => _buildBody(_historyController.loadingState.value)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildBody(LoadingState<List<HisListItem>?> loadingState) {
|
||||
|
||||
@@ -337,11 +337,15 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
const SizedBox(width: 6)
|
||||
],
|
||||
),
|
||||
body: Stack(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: Stack(
|
||||
children: [
|
||||
OrientationBuilder(
|
||||
builder: (context, orientation) {
|
||||
double padding = max(context.width / 2 - Grid.smallCardWidth, 0);
|
||||
double padding =
|
||||
max(context.width / 2 - Grid.smallCardWidth, 0);
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -369,13 +373,15 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
: EdgeInsets.only(
|
||||
left: padding / 4,
|
||||
bottom:
|
||||
MediaQuery.paddingOf(context).bottom + 80,
|
||||
MediaQuery.paddingOf(context).bottom +
|
||||
80,
|
||||
),
|
||||
sliver: _buildContent,
|
||||
),
|
||||
if (orientation == Orientation.portrait) ...[
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: padding),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
thickness: 8,
|
||||
@@ -386,14 +392,16 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: padding),
|
||||
sliver: SliverToBoxAdapter(child: replyHeader()),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: padding),
|
||||
sliver: Obx(
|
||||
() =>
|
||||
replyList(_htmlRenderCtr.loadingState.value),
|
||||
() => replyList(
|
||||
_htmlRenderCtr.loadingState.value),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -513,7 +521,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context)
|
||||
bottom:
|
||||
MediaQuery.paddingOf(context)
|
||||
.bottom),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
@@ -572,9 +581,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
semanticLabel: "转发",
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(
|
||||
15, 0, 15, 0),
|
||||
padding: const EdgeInsets
|
||||
.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor:
|
||||
Theme.of(context)
|
||||
.colorScheme
|
||||
@@ -632,8 +640,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
child: Builder(
|
||||
builder: (context) =>
|
||||
TextButton.icon(
|
||||
onPressed: () =>
|
||||
RequestUtils.onLikeDynamic(
|
||||
onPressed: () => RequestUtils
|
||||
.onLikeDynamic(
|
||||
_htmlRenderCtr.item.value,
|
||||
() {
|
||||
if (context.mounted) {
|
||||
@@ -670,7 +678,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
semanticLabel: _htmlRenderCtr
|
||||
semanticLabel:
|
||||
_htmlRenderCtr
|
||||
.item
|
||||
.value
|
||||
.modules
|
||||
@@ -682,9 +691,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
: "点赞",
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(
|
||||
15, 0, 15, 0),
|
||||
padding: const EdgeInsets
|
||||
.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor:
|
||||
Theme.of(context)
|
||||
.colorScheme
|
||||
@@ -753,6 +761,7 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,10 @@ class _LaterPageState extends State<LaterPage>
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
TabBar(
|
||||
SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: TabBar(
|
||||
isScrollable: true,
|
||||
controller: _tabController,
|
||||
tabAlignment: TabAlignment.start,
|
||||
@@ -107,14 +110,20 @@ class _LaterPageState extends State<LaterPage>
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: _baseCtr.enableMultiSelect.value
|
||||
? const NeverScrollableScrollPhysics()
|
||||
: const CustomTabBarViewScrollPhysics(),
|
||||
controller: _tabController,
|
||||
children:
|
||||
LaterViewType.values.map((item) => item.page).toList(),
|
||||
children: LaterViewType.values
|
||||
.map((item) => SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: item.page,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:PiliPlus/pages/live_room/send_dm_panel.dart';
|
||||
import 'package:PiliPlus/pages/live_room/widgets/chat.dart';
|
||||
import 'package:PiliPlus/pages/live_room/widgets/header_control.dart';
|
||||
import 'package:PiliPlus/services/service_locator.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
@@ -203,7 +204,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -228,9 +229,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
fit: BoxFit.cover,
|
||||
width: Get.width,
|
||||
height: Get.height,
|
||||
imageUrl: Utils.thumbnailImgUrl(
|
||||
_liveRoomController.roomInfoH5.value.roomInfo!
|
||||
.appBackground!),
|
||||
imageUrl: _liveRoomController.roomInfoH5.value
|
||||
.roomInfo!.appBackground!.http2https,
|
||||
)
|
||||
: Image.asset(
|
||||
'assets/images/live/default_bg.webp',
|
||||
@@ -239,7 +239,12 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
),
|
||||
),
|
||||
),
|
||||
isPortrait
|
||||
SafeArea(
|
||||
top: false,
|
||||
left: !isFullScreen,
|
||||
right: !isFullScreen,
|
||||
bottom: false,
|
||||
child: isPortrait
|
||||
? Obx(
|
||||
() {
|
||||
if (_liveRoomController.isPortrait.value) {
|
||||
@@ -258,6 +263,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
_buildBodyH,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -458,10 +464,13 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
children: [
|
||||
Obx(
|
||||
() => Container(
|
||||
margin:
|
||||
EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom),
|
||||
color: isFullScreen ? Colors.black : null,
|
||||
width: isFullScreen ? Get.size.width : videoWidth,
|
||||
height: isFullScreen ? Get.size.height : Get.size.width * 9 / 16,
|
||||
child: MediaQuery.removePadding(
|
||||
removeTop: true,
|
||||
removeRight: true,
|
||||
context: context,
|
||||
child: videoPlayerPanel(fill: Colors.transparent),
|
||||
@@ -469,15 +478,11 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SafeArea(
|
||||
left: false,
|
||||
top: false,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: _buildBottomWidget,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -173,6 +173,7 @@ class _MainAppState extends State<MainApp>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool isPortrait = context.orientation == Orientation.portrait;
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
onPopInvokedWithResult: (bool didPop, Object? result) async {
|
||||
@@ -200,8 +201,7 @@ class _MainAppState extends State<MainApp>
|
||||
body: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (useSideBar ||
|
||||
context.orientation == Orientation.landscape) ...[
|
||||
if (useSideBar || !isPortrait) ...[
|
||||
Obx(
|
||||
() => _mainController.navigationBars.length > 1
|
||||
? context.isTablet
|
||||
@@ -298,12 +298,14 @@ class _MainAppState extends State<MainApp>
|
||||
),
|
||||
],
|
||||
Expanded(
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
left: isPortrait,
|
||||
child: _mainController.mainTabBarView
|
||||
? CustomTabBarView(
|
||||
scrollDirection:
|
||||
context.orientation == Orientation.portrait
|
||||
? Axis.horizontal
|
||||
: Axis.vertical,
|
||||
isPortrait ? Axis.horizontal : Axis.vertical,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
controller: _mainController.controller,
|
||||
children: _mainController.pages,
|
||||
@@ -314,10 +316,10 @@ class _MainAppState extends State<MainApp>
|
||||
children: _mainController.pages,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: useSideBar ||
|
||||
context.orientation == Orientation.landscape
|
||||
bottomNavigationBar: useSideBar || !isPortrait
|
||||
? null
|
||||
: StreamBuilder(
|
||||
stream: _mainController.hideTabBar
|
||||
|
||||
@@ -40,7 +40,10 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
Color primary = Theme.of(context).colorScheme.primary;
|
||||
return Scaffold(
|
||||
return MediaQuery.removePadding(
|
||||
context: context,
|
||||
removeLeft: context.orientation == Orientation.landscape,
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 30,
|
||||
@@ -98,6 +101,7 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ class MemberControllerNew extends CommonDataController<Data, dynamic>
|
||||
late List<Tab> tabs;
|
||||
List<Tab2>? tab2;
|
||||
RxInt contributeInitialIndex = 0.obs;
|
||||
double top = 0;
|
||||
bool? hasSeasonOrSeries;
|
||||
final fromViewAid = Get.parameters['from_view_aid'];
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
late final String _heroTag;
|
||||
late final MemberControllerNew _userController;
|
||||
final _key = GlobalKey<ExtendedNestedScrollViewState>();
|
||||
int _offset = 120;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -45,8 +46,10 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
}
|
||||
|
||||
void listener() {
|
||||
if (_userController.scrollController.hasClients) {
|
||||
_userController.showUname.value =
|
||||
_userController.scrollController.offset >= 120;
|
||||
_userController.scrollController.offset >= _offset;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -57,138 +60,28 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_userController.top == 0) {
|
||||
_userController.top = MediaQuery.of(context).padding.top;
|
||||
}
|
||||
return Scaffold(
|
||||
extendBody: true,
|
||||
extendBodyBehindAppBar: true,
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Obx(
|
||||
() => _userController.loadingState.value is Success
|
||||
? LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return ExtendedNestedScrollView(
|
||||
key: _key,
|
||||
controller: _userController.scrollController,
|
||||
onlyOneScrollInBody: true,
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverOverlapAbsorber(
|
||||
handle: ExtendedNestedScrollView
|
||||
.sliverOverlapAbsorberHandleFor(context),
|
||||
sliver: _buildAppBar(
|
||||
isV: constraints.maxHeight > constraints.maxWidth,
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
body: _userController.tab2?.isNotEmpty == true
|
||||
? LayoutBuilder(
|
||||
builder: (context, _) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: ExtendedNestedScrollView
|
||||
.sliverOverlapAbsorberHandleFor(
|
||||
context)
|
||||
.layoutExtent ??
|
||||
0,
|
||||
),
|
||||
child: _buildBody,
|
||||
);
|
||||
},
|
||||
)
|
||||
: Center(child: const Text('EMPTY')),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Center(
|
||||
child: _buildUserInfo(_userController.loadingState.value),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildTab => Material(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: TabBar(
|
||||
controller: _userController.tabController,
|
||||
tabs: _userController.tabs,
|
||||
onTap: (value) {
|
||||
if (_userController.tabController?.indexIsChanging == false) {
|
||||
_key.currentState?.outerController.animToTop();
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _buildBody => SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: tabBarView(
|
||||
controller: _userController.tabController,
|
||||
children: _userController.tab2!.map((item) {
|
||||
return switch (item.param!) {
|
||||
'home' => MemberHome(heroTag: _heroTag),
|
||||
'dynamic' => MemberDynamicsPage(mid: _mid),
|
||||
'contribute' => Obx(
|
||||
() => MemberContribute(
|
||||
heroTag: _heroTag,
|
||||
initialIndex: _userController.contributeInitialIndex.value,
|
||||
mid: _mid,
|
||||
),
|
||||
),
|
||||
'bangumi' => MemberBangumi(
|
||||
heroTag: _heroTag,
|
||||
mid: _mid,
|
||||
),
|
||||
'favorite' => MemberFavorite(
|
||||
heroTag: _heroTag,
|
||||
mid: _mid,
|
||||
),
|
||||
_ => Center(child: Text(item.title ?? '')),
|
||||
};
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildAppBar({bool needTab = true, bool isV = true}) =>
|
||||
DynamicSliverAppBar(
|
||||
primary: false,
|
||||
leading: Padding(
|
||||
padding: EdgeInsets.only(top: _userController.top),
|
||||
child: const BackButton(),
|
||||
),
|
||||
hasTabBar: (_userController.tab2?.length ?? 0) > 1,
|
||||
toolbarHeight: kToolbarHeight + _userController.top,
|
||||
appBar: AppBar(
|
||||
forceMaterialTransparency: true,
|
||||
title: IgnorePointer(
|
||||
child: Obx(() => _userController.showUname.value &&
|
||||
child: Obx(
|
||||
() => _userController.showUname.value &&
|
||||
_userController.username != null
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(top: _userController.top),
|
||||
child: Text(_userController.username!),
|
||||
)
|
||||
: const SizedBox.shrink()),
|
||||
? Text(_userController.username!)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
pinned: true,
|
||||
flexibleSpace: _buildUserInfo(_userController.loadingState.value, isV),
|
||||
bottom: needTab && (_userController.tab2?.length ?? -1) > 1
|
||||
? PreferredSize(
|
||||
preferredSize: Size.fromHeight(48),
|
||||
child: _buildTab,
|
||||
)
|
||||
: null,
|
||||
actions: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: _userController.top),
|
||||
child: IconButton(
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => Get.toNamed(
|
||||
'/memberSearch?mid=$_mid&uname=${_userController.username}'),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: _userController.top),
|
||||
child: PopupMenuButton(
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
||||
if (_userController.ownerMid != _mid) ...[
|
||||
@@ -213,9 +106,7 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
children: [
|
||||
const Icon(Icons.share_outlined, size: 19),
|
||||
const SizedBox(width: 10),
|
||||
Text(_userController.ownerMid != _mid
|
||||
? '分享UP主'
|
||||
: '分享我的主页'),
|
||||
Text(_userController.ownerMid != _mid ? '分享UP主' : '分享我的主页'),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -259,10 +150,107 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
),
|
||||
body: Obx(
|
||||
() => _userController.loadingState.value is Success
|
||||
? LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return ExtendedNestedScrollView(
|
||||
key: _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
|
||||
? Column(
|
||||
children: [
|
||||
if ((_userController.tab2?.length ?? 0) > 1)
|
||||
_buildTab,
|
||||
Expanded(child: _buildBody),
|
||||
],
|
||||
)
|
||||
: Center(child: const Text('EMPTY')),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Center(
|
||||
child: _buildUserInfo(_userController.loadingState.value),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildTab => Material(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: TabBar(
|
||||
controller: _userController.tabController,
|
||||
tabs: _userController.tabs,
|
||||
onTap: (value) {
|
||||
if (_userController.tabController?.indexIsChanging == false) {
|
||||
_key.currentState?.outerController.animToTop();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _buildBody => SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: tabBarView(
|
||||
controller: _userController.tabController,
|
||||
children: _userController.tab2!.map((item) {
|
||||
return switch (item.param!) {
|
||||
'home' => MemberHome(heroTag: _heroTag),
|
||||
'dynamic' => MemberDynamicsPage(mid: _mid),
|
||||
'contribute' => Obx(
|
||||
() => MemberContribute(
|
||||
heroTag: _heroTag,
|
||||
initialIndex: _userController.contributeInitialIndex.value,
|
||||
mid: _mid,
|
||||
),
|
||||
),
|
||||
'bangumi' => MemberBangumi(
|
||||
heroTag: _heroTag,
|
||||
mid: _mid,
|
||||
),
|
||||
'favorite' => MemberFavorite(
|
||||
heroTag: _heroTag,
|
||||
mid: _mid,
|
||||
),
|
||||
_ => Center(child: Text(item.title ?? '')),
|
||||
};
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildAppBar({bool isV = true}) {
|
||||
return DynamicSliverAppBar(
|
||||
pinned: true,
|
||||
primary: false,
|
||||
automaticallyImplyLeading: false,
|
||||
toolbarHeight: kToolbarHeight + MediaQuery.paddingOf(context).top,
|
||||
flexibleSpace: _buildUserInfo(_userController.loadingState.value, isV),
|
||||
callback: (value) {
|
||||
_offset = (value - 56 - MediaQuery.paddingOf(context).top).toInt();
|
||||
listener();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _errorWidget(msg) {
|
||||
return errorWidget(
|
||||
|
||||
@@ -118,6 +118,12 @@ class UserInfoCard extends StatelessWidget {
|
||||
onTap: () => Utils.copyText(card.name!),
|
||||
child: Text(
|
||||
card.name!,
|
||||
strutStyle: StrutStyle(
|
||||
height: 1,
|
||||
leading: 0,
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 17,
|
||||
@@ -136,8 +142,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
),
|
||||
if (card.vip?.vipStatus == 1)
|
||||
CachedNetworkImage(
|
||||
imageUrl:
|
||||
Utils.thumbnailImgUrl(card.vip!.label!.image!.http2https),
|
||||
imageUrl: Utils.thumbnailImgUrl(card.vip!.label!.image!, 80),
|
||||
height: 20,
|
||||
placeholder: (context, url) {
|
||||
return const SizedBox.shrink();
|
||||
@@ -612,7 +617,10 @@ class UserInfoCard extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(context),
|
||||
// _buildHeader(context),
|
||||
SizedBox(
|
||||
height: Get.mediaQuery.padding.bottom + 56,
|
||||
),
|
||||
SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
|
||||
@@ -39,7 +39,10 @@ class _MemberCoinPageState extends State<MemberCoinPage> {
|
||||
appBar: AppBar(
|
||||
title: Text('${widget.mid == _ownerMid ? '我' : '${widget.name}'}的最近投币'),
|
||||
),
|
||||
body: CustomScrollView(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
@@ -52,6 +55,7 @@ class _MemberCoinPageState extends State<MemberCoinPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,10 @@ class _MemberLikePageState extends State<MemberLikePage> {
|
||||
appBar: AppBar(
|
||||
title: Text('${widget.mid == _ownerMid ? '我' : '${widget.name}'}的推荐'),
|
||||
),
|
||||
body: CustomScrollView(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
@@ -52,6 +55,7 @@ class _MemberLikePageState extends State<MemberLikePage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ class _SearchArchiveState extends State<SearchArchive>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return refreshIndicator(
|
||||
return SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await widget.ctr.refreshArchive();
|
||||
},
|
||||
@@ -45,6 +48,7 @@ class _SearchArchiveState extends State<SearchArchive>
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,10 @@ class _SearchDynamicState extends State<SearchDynamic>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return refreshIndicator(
|
||||
return SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await widget.ctr.refreshDynamic();
|
||||
},
|
||||
@@ -46,6 +49,7 @@ class _SearchDynamicState extends State<SearchDynamic>
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,10 @@ class _MemberSearchPageState extends State<MemberSearchPage> {
|
||||
() => _memberSearchCtr.hasData.value
|
||||
? Column(
|
||||
children: [
|
||||
TabBar(
|
||||
SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: TabBar(
|
||||
controller: _memberSearchCtr.tabController,
|
||||
tabs: [
|
||||
Obx(
|
||||
@@ -72,6 +75,7 @@ class _MemberSearchPageState extends State<MemberSearchPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: tabBarView(
|
||||
controller: _memberSearchCtr.tabController,
|
||||
|
||||
@@ -52,7 +52,9 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('选择应用主题')),
|
||||
body: ListView(
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
child: ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
@@ -82,7 +84,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
child: const Icon(Icons.flashlight_on_outlined),
|
||||
),
|
||||
title: Text('主题模式', style: titleStyle),
|
||||
subtitle: Obx(() => Text('当前模式:${ctr.themeType.value.description}',
|
||||
subtitle: Obx(() => Text(
|
||||
'当前模式:${ctr.themeType.value.description}',
|
||||
style: subTitleStyle)),
|
||||
),
|
||||
Obx(
|
||||
@@ -182,7 +185,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
() => SizedBox(
|
||||
height: ctr.type.value == 0 ? 0 : null,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 12, left: 12, right: 12),
|
||||
padding:
|
||||
const EdgeInsets.only(top: 12, left: 12, right: 12),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 22,
|
||||
@@ -194,7 +198,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
ctr.currentColor.value = index;
|
||||
ctr.setting.put(SettingBoxKey.customColor, index);
|
||||
ctr.setting
|
||||
.put(SettingBoxKey.customColor, index);
|
||||
Get.forceAppUpdate();
|
||||
},
|
||||
child: Column(
|
||||
@@ -213,9 +218,11 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
),
|
||||
),
|
||||
child: AnimatedOpacity(
|
||||
opacity:
|
||||
ctr.currentColor.value == index ? 1 : 0,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
opacity: ctr.currentColor.value == index
|
||||
? 1
|
||||
: 0,
|
||||
duration:
|
||||
const Duration(milliseconds: 200),
|
||||
child: const Icon(
|
||||
Icons.done,
|
||||
color: Colors.black,
|
||||
@@ -229,7 +236,9 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ctr.currentColor.value != index
|
||||
? Theme.of(context).colorScheme.outline
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
: null,
|
||||
),
|
||||
),
|
||||
@@ -267,6 +276,7 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
||||
const SizedBox(width: 12)
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Center(
|
||||
@@ -60,12 +61,7 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(
|
||||
left: 20,
|
||||
right: 20,
|
||||
top: 20,
|
||||
bottom: MediaQuery.of(context).padding.bottom + 20,
|
||||
),
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
@@ -101,6 +97,7 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,27 +144,39 @@ class _LogsPageState extends State<LogsPage> {
|
||||
],
|
||||
),
|
||||
body: logsContent.isNotEmpty
|
||||
? ListView.builder(
|
||||
? SafeArea(
|
||||
bottom: false,
|
||||
child: ListView.separated(
|
||||
itemCount: logsContent.length,
|
||||
itemBuilder: (context, index) {
|
||||
final log = logsContent[index];
|
||||
if (log['date'] is DateTime) {
|
||||
latestLog ??= log['date'];
|
||||
}
|
||||
return Column(
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
Text(
|
||||
log['date'].toString(),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.fontSize,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
visualDensity:
|
||||
VisualDensity(horizontal: -2, vertical: -2),
|
||||
),
|
||||
onPressed: () async {
|
||||
await Utils.copyText('```\n${log['body']}\n```',
|
||||
needToast: false);
|
||||
@@ -183,23 +195,28 @@ class _LogsPageState extends State<LogsPage> {
|
||||
)
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Card(
|
||||
const SizedBox(height: 5),
|
||||
Card(
|
||||
elevation: 1,
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
child: Padding(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: SelectableText(log['body']),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(indent: 12, endIndent: 12),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => const Divider(
|
||||
indent: 12,
|
||||
endIndent: 12,
|
||||
height: 24,
|
||||
),
|
||||
),
|
||||
)
|
||||
: errorWidget(),
|
||||
: scrollErrorWidget(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,9 +210,9 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
child: ListView(
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
|
||||
@@ -75,22 +75,25 @@ class _SettingsSearchPageState extends State<SettingsSearchPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Obx(
|
||||
() => _list.isEmpty
|
||||
? CustomScrollView(
|
||||
slivers: [HttpError()],
|
||||
)
|
||||
: CustomScrollView(
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverWaterfallFlow.extent(
|
||||
Obx(
|
||||
() => _list.isEmpty
|
||||
? HttpError()
|
||||
: SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: SliverWaterfallFlow.extent(
|
||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||
children: [
|
||||
..._list.map((item) => item.widget),
|
||||
SizedBox(
|
||||
height: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -121,13 +121,23 @@ class _SettingPageState extends State<SettingPage> {
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(flex: 40, child: _buildList),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: MediaQuery.removePadding(
|
||||
context: context,
|
||||
removeRight: true,
|
||||
child: _buildList,
|
||||
),
|
||||
),
|
||||
VerticalDivider(
|
||||
width: 1,
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
Expanded(
|
||||
flex: 60,
|
||||
flex: 6,
|
||||
child: MediaQuery.removePadding(
|
||||
context: context,
|
||||
removeLeft: true,
|
||||
child: switch (_type) {
|
||||
'privacySetting' => PrivacySetting(showAppBar: false),
|
||||
'recommendSetting' => RecommendSetting(showAppBar: false),
|
||||
@@ -139,6 +149,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
'about' => AboutPage(showAppBar: false),
|
||||
_ => const SizedBox.shrink(),
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
||||
@@ -23,7 +23,10 @@ class _SubPageState extends State<SubPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('我的订阅')),
|
||||
body: refreshIndicator(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _subController.onRefresh();
|
||||
},
|
||||
@@ -38,6 +41,7 @@ class _SubPageState extends State<SubPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
||||
|
||||
Widget get _buildCount => SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14),
|
||||
padding: const EdgeInsets.only(top: 12, bottom: 8, left: 14),
|
||||
child: Obx(
|
||||
() => Text(
|
||||
'共${_subDetailController.mediaCount}条视频',
|
||||
@@ -118,7 +118,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
||||
);
|
||||
|
||||
Widget get _buildAppBar => SliverAppBar(
|
||||
expandedHeight: 215 - MediaQuery.paddingOf(context).bottom,
|
||||
expandedHeight: 210 - MediaQuery.paddingOf(context).top,
|
||||
pinned: true,
|
||||
title: Obx(
|
||||
() {
|
||||
@@ -158,7 +158,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
||||
top: kTextTabBarHeight + MediaQuery.of(context).padding.top + 15,
|
||||
left: 12,
|
||||
right: 12,
|
||||
bottom: 20,
|
||||
bottom: 12,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
@@ -31,11 +31,7 @@ class _WhisperPageState extends State<WhisperPage> {
|
||||
child: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
SliverSafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
sliver: _buildTopItems,
|
||||
),
|
||||
_buildTopItems,
|
||||
Obx(() => _buildBody(_whisperController.loadingState.value)),
|
||||
],
|
||||
),
|
||||
@@ -90,11 +86,14 @@ class _WhisperPageState extends State<WhisperPage> {
|
||||
};
|
||||
}
|
||||
|
||||
Widget get _buildTopItems => SliverToBoxAdapter(
|
||||
Widget get _buildTopItems => SliverSafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children:
|
||||
List.generate(_whisperController.msgFeedTopItems.length, (index) {
|
||||
children: List.generate(_whisperController.msgFeedTopItems.length,
|
||||
(index) {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Padding(
|
||||
@@ -108,8 +107,8 @@ class _WhisperPageState extends State<WhisperPage> {
|
||||
() => Badge(
|
||||
isLabelVisible:
|
||||
_whisperController.unreadCounts[index] > 0,
|
||||
label:
|
||||
Text(" ${_whisperController.unreadCounts[index]} "),
|
||||
label: Text(
|
||||
" ${_whisperController.unreadCounts[index]} "),
|
||||
alignment: Alignment.topRight,
|
||||
child: CircleAvatar(
|
||||
radius: 22,
|
||||
@@ -144,5 +143,6 @@ class _WhisperPageState extends State<WhisperPage> {
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,10 @@ class _WhisperDetailPageState
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Listener(
|
||||
@@ -110,6 +113,7 @@ class _WhisperDetailPageState
|
||||
buildPanelContainer(Theme.of(context).colorScheme.onInverseSurface),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user