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.forceMaterialTransparency = false,
|
||||||
this.clipBehavior,
|
this.clipBehavior,
|
||||||
this.appBarClipper,
|
this.appBarClipper,
|
||||||
this.hasTabBar = false,
|
this.callback,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool hasTabBar;
|
final ValueChanged<double>? callback;
|
||||||
final Widget? flexibleSpace;
|
final Widget? flexibleSpace;
|
||||||
final Widget? leading;
|
final Widget? leading;
|
||||||
final bool automaticallyImplyLeading;
|
final bool automaticallyImplyLeading;
|
||||||
@@ -113,6 +113,7 @@ class _DynamicSliverAppBarState extends State<DynamicSliverAppBar> {
|
|||||||
_height = (_childKey.currentContext!.findRenderObject()! as RenderBox)
|
_height = (_childKey.currentContext!.findRenderObject()! as RenderBox)
|
||||||
.size
|
.size
|
||||||
.height;
|
.height;
|
||||||
|
widget.callback?.call(_height);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -166,7 +167,7 @@ class _DynamicSliverAppBarState extends State<DynamicSliverAppBar> {
|
|||||||
onStretchTrigger: widget.onStretchTrigger,
|
onStretchTrigger: widget.onStretchTrigger,
|
||||||
shape: widget.shape,
|
shape: widget.shape,
|
||||||
toolbarHeight: widget.toolbarHeight,
|
toolbarHeight: widget.toolbarHeight,
|
||||||
expandedHeight: _height + (widget.hasTabBar ? 48 : 0),
|
expandedHeight: _height,
|
||||||
leadingWidth: widget.leadingWidth,
|
leadingWidth: widget.leadingWidth,
|
||||||
toolbarTextStyle: widget.toolbarTextStyle,
|
toolbarTextStyle: widget.toolbarTextStyle,
|
||||||
titleTextStyle: widget.titleTextStyle,
|
titleTextStyle: widget.titleTextStyle,
|
||||||
|
|||||||
@@ -51,30 +51,33 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
|||||||
int count = (data.order?.isNotEmpty == true ? 1 : 0) +
|
int count = (data.order?.isNotEmpty == true ? 1 : 0) +
|
||||||
(data.filter?.length ?? 0);
|
(data.filter?.length ?? 0);
|
||||||
if (count == 0) return const SizedBox.shrink();
|
if (count == 0) return const SizedBox.shrink();
|
||||||
return CustomScrollView(
|
return SafeArea(
|
||||||
slivers: [
|
bottom: false,
|
||||||
if (widget.indexType != null)
|
child: CustomScrollView(
|
||||||
SliverToBoxAdapter(child: const SizedBox(height: 12)),
|
slivers: [
|
||||||
SliverToBoxAdapter(
|
if (widget.indexType != null)
|
||||||
child: AnimatedSize(
|
SliverToBoxAdapter(child: const SizedBox(height: 12)),
|
||||||
curve: Curves.easeInOut,
|
SliverToBoxAdapter(
|
||||||
alignment: Alignment.topCenter,
|
child: AnimatedSize(
|
||||||
duration: const Duration(milliseconds: 200),
|
curve: Curves.easeInOut,
|
||||||
child: count > 5
|
alignment: Alignment.topCenter,
|
||||||
? Obx(() => _buildSortWidget(count, data))
|
duration: const Duration(milliseconds: 200),
|
||||||
: _buildSortWidget(count, data),
|
child: count > 5
|
||||||
|
? Obx(() => _buildSortWidget(count, data))
|
||||||
|
: _buildSortWidget(count, data),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
SliverPadding(
|
||||||
SliverPadding(
|
padding: EdgeInsets.only(
|
||||||
padding: EdgeInsets.only(
|
left: StyleString.safeSpace,
|
||||||
left: StyleString.safeSpace,
|
right: StyleString.safeSpace,
|
||||||
right: StyleString.safeSpace,
|
top: 12,
|
||||||
top: 12,
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
),
|
||||||
|
sliver: Obx(() => _buildList(_ctr.loadingState.value)),
|
||||||
),
|
),
|
||||||
sliver: Obx(() => _buildList(_ctr.loadingState.value)),
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
Error() => scrollErrorWidget(
|
Error() => scrollErrorWidget(
|
||||||
|
|||||||
@@ -248,10 +248,14 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
|||||||
length: types.length,
|
length: types.length,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
SafeArea(
|
||||||
tabs: titles
|
top: false,
|
||||||
.map((title) => Tab(text: title))
|
bottom: false,
|
||||||
.toList()),
|
child: TabBar(
|
||||||
|
tabs: titles
|
||||||
|
.map((title) => Tab(text: title))
|
||||||
|
.toList()),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: tabBarView(
|
child: tabBarView(
|
||||||
children: types
|
children: types
|
||||||
|
|||||||
@@ -48,12 +48,16 @@ abstract class CommonSearchPageState<S extends CommonSearchPage, R, T>
|
|||||||
onSubmitted: (value) => controller.onRefresh(),
|
onSubmitted: (value) => controller.onRefresh(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: CustomScrollView(
|
body: SafeArea(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
top: false,
|
||||||
controller: controller.scrollController,
|
bottom: false,
|
||||||
slivers: [
|
child: CustomScrollView(
|
||||||
Obx(() => _buildBody(controller.loadingState.value)),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
],
|
controller: controller.scrollController,
|
||||||
|
slivers: [
|
||||||
|
Obx(() => _buildBody(controller.loadingState.value)),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,10 +103,6 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
super.initState();
|
super.initState();
|
||||||
// floor 1原创 2转发
|
// floor 1原创 2转发
|
||||||
init();
|
init();
|
||||||
// if (action == 'comment') {
|
|
||||||
// _visibleTitle = true;
|
|
||||||
// _titleStreamC.add(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
_fabAnimationCtr = AnimationController(
|
_fabAnimationCtr = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
@@ -340,14 +336,18 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
]
|
]
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
body: context.orientation == Orientation.portrait
|
body: SafeArea(
|
||||||
? refreshIndicator(
|
top: false,
|
||||||
onRefresh: () async {
|
bottom: false,
|
||||||
await _dynamicDetailController.onRefresh();
|
child: context.orientation == Orientation.portrait
|
||||||
},
|
? refreshIndicator(
|
||||||
child: _buildBody(context.orientation),
|
onRefresh: () async {
|
||||||
)
|
await _dynamicDetailController.onRefresh();
|
||||||
: _buildBody(context.orientation),
|
},
|
||||||
|
child: _buildBody(context.orientation),
|
||||||
|
)
|
||||||
|
: _buildBody(context.orientation),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,14 +37,17 @@ class _FansPageState extends State<FansPage> {
|
|||||||
_fansController.isOwner.value ? '我的粉丝' : '${_fansController.name}的粉丝',
|
_fansController.isOwner.value ? '我的粉丝' : '${_fansController.name}的粉丝',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: refreshIndicator(
|
body: SafeArea(
|
||||||
onRefresh: () async => await _fansController.onRefresh(),
|
bottom: false,
|
||||||
child: CustomScrollView(
|
child: refreshIndicator(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
onRefresh: () async => await _fansController.onRefresh(),
|
||||||
controller: _fansController.scrollController,
|
child: CustomScrollView(
|
||||||
slivers: [
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
Obx(() => _buildBody(_fansController.loadingState.value)),
|
controller: _fansController.scrollController,
|
||||||
],
|
slivers: [
|
||||||
|
Obx(() => _buildBody(_fansController.loadingState.value)),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -87,7 +87,11 @@ class _FavFolderSortPageState extends State<FavFolderSortPage> {
|
|||||||
const SizedBox(width: 16),
|
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(
|
body: tabBarView(
|
||||||
controller: _tabController,
|
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),
|
const SizedBox(width: 16),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: _buildBody,
|
body: SafeArea(
|
||||||
|
top: false,
|
||||||
|
bottom: false,
|
||||||
|
child: _buildBody,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,296 +75,319 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
)
|
)
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
body: refreshIndicator(
|
body: SafeArea(
|
||||||
onRefresh: () async {
|
top: false,
|
||||||
await _favDetailController.onRefresh();
|
bottom: false,
|
||||||
},
|
child: refreshIndicator(
|
||||||
child: CustomScrollView(
|
onRefresh: () async {
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
await _favDetailController.onRefresh();
|
||||||
controller: _favDetailController.scrollController,
|
},
|
||||||
slivers: [
|
child: CustomScrollView(
|
||||||
SliverAppBar(
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
leading: _favDetailController.enableMultiSelect.value
|
controller: _favDetailController.scrollController,
|
||||||
? IconButton(
|
slivers: [
|
||||||
tooltip: '取消',
|
SliverAppBar(
|
||||||
onPressed: _favDetailController.handleSelect,
|
leading: _favDetailController.enableMultiSelect.value
|
||||||
icon: const Icon(Icons.close_outlined),
|
? IconButton(
|
||||||
)
|
tooltip: '取消',
|
||||||
: null,
|
onPressed: _favDetailController.handleSelect,
|
||||||
expandedHeight: 220 - MediaQuery.of(context).padding.top,
|
icon: const Icon(Icons.close_outlined),
|
||||||
pinned: true,
|
)
|
||||||
title: _favDetailController.enableMultiSelect.value
|
: null,
|
||||||
? Text(
|
expandedHeight: 200 - MediaQuery.of(context).padding.top,
|
||||||
'已选: ${_favDetailController.checkedCount.value}',
|
pinned: true,
|
||||||
)
|
title: _favDetailController.enableMultiSelect.value
|
||||||
: Obx(
|
? Text(
|
||||||
() => AnimatedOpacity(
|
'已选: ${_favDetailController.checkedCount.value}',
|
||||||
opacity:
|
)
|
||||||
_favDetailController.titleCtr.value ? 1 : 0,
|
: Obx(
|
||||||
curve: Curves.easeOut,
|
() => AnimatedOpacity(
|
||||||
duration: const Duration(milliseconds: 500),
|
opacity:
|
||||||
child: Column(
|
_favDetailController.titleCtr.value ? 1 : 0,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
curve: Curves.easeOut,
|
||||||
children: [
|
duration: const Duration(milliseconds: 500),
|
||||||
Text(
|
child: Column(
|
||||||
_favDetailController.item.value.title ?? '',
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style:
|
children: [
|
||||||
Theme.of(context).textTheme.titleMedium,
|
Text(
|
||||||
),
|
_favDetailController.item.value.title ?? '',
|
||||||
Text(
|
style:
|
||||||
'共${_favDetailController.item.value.mediaCount}条视频',
|
Theme.of(context).textTheme.titleMedium,
|
||||||
style:
|
),
|
||||||
Theme.of(context).textTheme.labelMedium,
|
Text(
|
||||||
)
|
'共${_favDetailController.item.value.mediaCount}条视频',
|
||||||
],
|
style:
|
||||||
),
|
Theme.of(context).textTheme.labelMedium,
|
||||||
),
|
)
|
||||||
),
|
],
|
||||||
actions: _favDetailController.enableMultiSelect.value
|
|
||||||
? [
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
visualDensity:
|
|
||||||
VisualDensity(horizontal: -2, vertical: -2),
|
|
||||||
),
|
|
||||||
onPressed: () =>
|
|
||||||
_favDetailController.handleSelect(true),
|
|
||||||
child: const Text('全选'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
visualDensity:
|
|
||||||
VisualDensity(horizontal: -2, vertical: -2),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
RequestUtils.onCopyOrMove<FavDetailData,
|
|
||||||
FavDetailItemData>(
|
|
||||||
context: context,
|
|
||||||
isCopy: true,
|
|
||||||
ctr: _favDetailController,
|
|
||||||
mediaId: _favDetailController.mediaId,
|
|
||||||
mid: _favDetailController.mid,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'复制',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onSurfaceVariant,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextButton(
|
actions: _favDetailController.enableMultiSelect.value
|
||||||
style: TextButton.styleFrom(
|
? [
|
||||||
visualDensity:
|
TextButton(
|
||||||
VisualDensity(horizontal: -2, vertical: -2),
|
style: TextButton.styleFrom(
|
||||||
),
|
visualDensity:
|
||||||
onPressed: () {
|
VisualDensity(horizontal: -2, vertical: -2),
|
||||||
RequestUtils.onCopyOrMove<FavDetailData,
|
|
||||||
FavDetailItemData>(
|
|
||||||
context: context,
|
|
||||||
isCopy: false,
|
|
||||||
ctr: _favDetailController,
|
|
||||||
mediaId: _favDetailController.mediaId,
|
|
||||||
mid: _favDetailController.mid,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'移动',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onSurfaceVariant,
|
|
||||||
),
|
),
|
||||||
|
onPressed: () =>
|
||||||
|
_favDetailController.handleSelect(true),
|
||||||
|
child: const Text('全选'),
|
||||||
),
|
),
|
||||||
),
|
TextButton(
|
||||||
TextButton(
|
style: TextButton.styleFrom(
|
||||||
style: TextButton.styleFrom(
|
visualDensity:
|
||||||
visualDensity:
|
VisualDensity(horizontal: -2, vertical: -2),
|
||||||
VisualDensity(horizontal: -2, vertical: -2),
|
),
|
||||||
),
|
onPressed: () {
|
||||||
onPressed: () =>
|
RequestUtils.onCopyOrMove<FavDetailData,
|
||||||
_favDetailController.onDelChecked(context),
|
FavDetailItemData>(
|
||||||
child: Text(
|
context: context,
|
||||||
'删除',
|
isCopy: true,
|
||||||
style: TextStyle(
|
ctr: _favDetailController,
|
||||||
color: Theme.of(context).colorScheme.error),
|
mediaId: _favDetailController.mediaId,
|
||||||
),
|
mid: _favDetailController.mid,
|
||||||
),
|
);
|
||||||
const SizedBox(width: 6),
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
IconButton(
|
|
||||||
tooltip: '搜索',
|
|
||||||
onPressed: () => Get.toNamed(
|
|
||||||
'/favSearch',
|
|
||||||
arguments: {
|
|
||||||
'type': 0,
|
|
||||||
'mediaId': int.parse(mediaId),
|
|
||||||
'title': _favDetailController.item.value.title,
|
|
||||||
'count':
|
|
||||||
_favDetailController.item.value.mediaCount,
|
|
||||||
'isOwner': _favDetailController.isOwner.value,
|
|
||||||
},
|
},
|
||||||
|
child: Text(
|
||||||
|
'复制',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
icon: const Icon(Icons.search_outlined),
|
TextButton(
|
||||||
),
|
style: TextButton.styleFrom(
|
||||||
Obx(
|
visualDensity:
|
||||||
() => _favDetailController.isOwner.value
|
VisualDensity(horizontal: -2, vertical: -2),
|
||||||
? PopupMenuButton(
|
),
|
||||||
icon: const Icon(Icons.more_vert),
|
onPressed: () {
|
||||||
itemBuilder: (context) => [
|
RequestUtils.onCopyOrMove<FavDetailData,
|
||||||
PopupMenuItem(
|
FavDetailItemData>(
|
||||||
onTap: () {
|
context: context,
|
||||||
Get.toNamed(
|
isCopy: false,
|
||||||
'/createFav',
|
ctr: _favDetailController,
|
||||||
parameters: {'mediaId': mediaId},
|
mediaId: _favDetailController.mediaId,
|
||||||
)?.then((res) {
|
mid: _favDetailController.mid,
|
||||||
if (res is FavFolderItemData) {
|
);
|
||||||
_favDetailController.item.value =
|
},
|
||||||
res;
|
child: Text(
|
||||||
}
|
'移动',
|
||||||
});
|
style: TextStyle(
|
||||||
},
|
color: Theme.of(context)
|
||||||
child: Text('编辑信息'),
|
.colorScheme
|
||||||
),
|
.onSurfaceVariant,
|
||||||
PopupMenuItem(
|
),
|
||||||
onTap: () {
|
),
|
||||||
UserHttp.cleanFav(mediaId: mediaId)
|
),
|
||||||
.then((data) {
|
TextButton(
|
||||||
if (data['status']) {
|
style: TextButton.styleFrom(
|
||||||
SmartDialog.showToast('清除成功');
|
visualDensity:
|
||||||
Future.delayed(
|
VisualDensity(horizontal: -2, vertical: -2),
|
||||||
const Duration(
|
),
|
||||||
milliseconds: 200), () {
|
onPressed: () =>
|
||||||
_favDetailController.onReload();
|
_favDetailController.onDelChecked(context),
|
||||||
});
|
child: Text(
|
||||||
} else {
|
'删除',
|
||||||
SmartDialog.showToast(
|
style: TextStyle(
|
||||||
data['msg']);
|
color: Theme.of(context).colorScheme.error),
|
||||||
}
|
),
|
||||||
});
|
),
|
||||||
},
|
const SizedBox(width: 6),
|
||||||
child: Text('清除失效内容'),
|
]
|
||||||
),
|
: [
|
||||||
PopupMenuItem(
|
IconButton(
|
||||||
onTap: () {
|
tooltip: '搜索',
|
||||||
if (_favDetailController.loadingState
|
onPressed: () => Get.toNamed(
|
||||||
.value is Success &&
|
'/favSearch',
|
||||||
((_favDetailController
|
arguments: {
|
||||||
.loadingState
|
'type': 0,
|
||||||
.value as Success)
|
'mediaId': int.parse(mediaId),
|
||||||
.response as List?)
|
'title':
|
||||||
?.isNotEmpty ==
|
_favDetailController.item.value.title,
|
||||||
true) {
|
'count': _favDetailController
|
||||||
if ((_favDetailController.item.value
|
.item.value.mediaCount,
|
||||||
.mediaCount ??
|
'isOwner': _favDetailController.isOwner.value,
|
||||||
0) >
|
},
|
||||||
1000) {
|
),
|
||||||
SmartDialog.showToast(
|
icon: const Icon(Icons.search_outlined),
|
||||||
'内容太多啦!超过1000不支持排序');
|
),
|
||||||
return;
|
Obx(
|
||||||
}
|
() => _favDetailController.isOwner.value
|
||||||
Get.to(
|
? PopupMenuButton(
|
||||||
FavSortPage(
|
icon: const Icon(Icons.more_vert),
|
||||||
favDetailController:
|
itemBuilder: (context) => [
|
||||||
_favDetailController),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text('排序'),
|
|
||||||
),
|
|
||||||
if (!Utils.isDefaultFav(
|
|
||||||
_favDetailController
|
|
||||||
.item.value.attr ??
|
|
||||||
0))
|
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showConfirmDialog(
|
Get.toNamed(
|
||||||
context: context,
|
'/createFav',
|
||||||
title: '确定删除该收藏夹?',
|
parameters: {'mediaId': mediaId},
|
||||||
onConfirm: () {
|
)?.then((res) {
|
||||||
UserHttp.deleteFolder(
|
if (res is FavFolderItemData) {
|
||||||
mediaIds: [mediaId])
|
_favDetailController
|
||||||
.then((data) {
|
.item.value = res;
|
||||||
if (data['status']) {
|
}
|
||||||
SmartDialog.showToast(
|
});
|
||||||
'删除成功');
|
|
||||||
Get.back(result: true);
|
|
||||||
} else {
|
|
||||||
SmartDialog.showToast(
|
|
||||||
data['msg']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text('编辑信息'),
|
||||||
'删除',
|
),
|
||||||
style: TextStyle(
|
PopupMenuItem(
|
||||||
color: Theme.of(context)
|
onTap: () {
|
||||||
.colorScheme
|
UserHttp.cleanFav(mediaId: mediaId)
|
||||||
.error,
|
.then((data) {
|
||||||
|
if (data['status']) {
|
||||||
|
SmartDialog.showToast('清除成功');
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(
|
||||||
|
milliseconds: 200), () {
|
||||||
|
_favDetailController
|
||||||
|
.onReload();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SmartDialog.showToast(
|
||||||
|
data['msg']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Text('清除失效内容'),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () {
|
||||||
|
if (_favDetailController
|
||||||
|
.loadingState
|
||||||
|
.value is Success &&
|
||||||
|
((_favDetailController
|
||||||
|
.loadingState
|
||||||
|
.value
|
||||||
|
as Success)
|
||||||
|
.response as List?)
|
||||||
|
?.isNotEmpty ==
|
||||||
|
true) {
|
||||||
|
if ((_favDetailController.item
|
||||||
|
.value.mediaCount ??
|
||||||
|
0) >
|
||||||
|
1000) {
|
||||||
|
SmartDialog.showToast(
|
||||||
|
'内容太多啦!超过1000不支持排序');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Get.to(
|
||||||
|
FavSortPage(
|
||||||
|
favDetailController:
|
||||||
|
_favDetailController),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text('排序'),
|
||||||
|
),
|
||||||
|
if (!Utils.isDefaultFav(
|
||||||
|
_favDetailController
|
||||||
|
.item.value.attr ??
|
||||||
|
0))
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () {
|
||||||
|
showConfirmDialog(
|
||||||
|
context: context,
|
||||||
|
title: '确定删除该收藏夹?',
|
||||||
|
onConfirm: () {
|
||||||
|
UserHttp.deleteFolder(
|
||||||
|
mediaIds: [mediaId])
|
||||||
|
.then((data) {
|
||||||
|
if (data['status']) {
|
||||||
|
SmartDialog.showToast(
|
||||||
|
'删除成功');
|
||||||
|
Get.back(result: true);
|
||||||
|
} else {
|
||||||
|
SmartDialog.showToast(
|
||||||
|
data['msg']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'删除',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.error,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
)
|
||||||
)
|
: const SizedBox.shrink(),
|
||||||
: const SizedBox.shrink(),
|
),
|
||||||
),
|
const SizedBox(width: 6),
|
||||||
const SizedBox(width: 6),
|
],
|
||||||
],
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
background: Container(
|
||||||
background: Container(
|
padding: EdgeInsets.only(
|
||||||
padding: EdgeInsets.only(
|
top: kTextTabBarHeight +
|
||||||
top: kTextTabBarHeight +
|
MediaQuery.of(context).padding.top +
|
||||||
MediaQuery.of(context).padding.top +
|
10,
|
||||||
10,
|
left: 14,
|
||||||
left: 14,
|
right: 20,
|
||||||
right: 20,
|
),
|
||||||
),
|
child: SizedBox(
|
||||||
child: SizedBox(
|
height: 110,
|
||||||
height: 110,
|
child: Obx(
|
||||||
child: Obx(
|
() => Row(
|
||||||
() => Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
Hero(
|
||||||
Hero(
|
tag: _favDetailController.heroTag,
|
||||||
tag: _favDetailController.heroTag,
|
child: NetworkImgLayer(
|
||||||
child: NetworkImgLayer(
|
width: 180,
|
||||||
width: 180,
|
height: 110,
|
||||||
height: 110,
|
src: _favDetailController.item.value.cover,
|
||||||
src: _favDetailController.item.value.cover,
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 14),
|
||||||
const SizedBox(width: 14),
|
Expanded(
|
||||||
Expanded(
|
child: SizedBox(
|
||||||
child: SizedBox(
|
height: 110,
|
||||||
height: 110,
|
child: Column(
|
||||||
child: Column(
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment:
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
MainAxisAlignment.start,
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
|
||||||
_favDetailController.item.value.title ??
|
|
||||||
'',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.titleMedium!
|
|
||||||
.fontSize,
|
|
||||||
fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
if (_favDetailController
|
|
||||||
.item.value.intro?.isNotEmpty ==
|
|
||||||
true)
|
|
||||||
Text(
|
Text(
|
||||||
_favDetailController
|
_favDetailController
|
||||||
.item.value.intro ??
|
.item.value.title ??
|
||||||
|
'',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.titleMedium!
|
||||||
|
.fontSize,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
if (_favDetailController
|
||||||
|
.item.value.intro?.isNotEmpty ==
|
||||||
|
true)
|
||||||
|
Text(
|
||||||
|
_favDetailController
|
||||||
|
.item.value.intro ??
|
||||||
|
'',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelSmall!
|
||||||
|
.fontSize,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
_favDetailController
|
||||||
|
.item.value.upper?.name ??
|
||||||
'',
|
'',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: Theme.of(context)
|
fontSize: Theme.of(context)
|
||||||
@@ -375,48 +398,36 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
.colorScheme
|
.colorScheme
|
||||||
.outline),
|
.outline),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const Spacer(),
|
||||||
Text(
|
if (_favDetailController
|
||||||
_favDetailController
|
.item.value.attr !=
|
||||||
.item.value.upper?.name ??
|
null)
|
||||||
'',
|
Text(
|
||||||
style: TextStyle(
|
'共${_favDetailController.item.value.mediaCount}条视频 · ${Utils.isPublicFavText(_favDetailController.item.value.attr ?? 0)}',
|
||||||
fontSize: Theme.of(context)
|
style: TextStyle(
|
||||||
.textTheme
|
fontSize: Theme.of(context)
|
||||||
.labelSmall!
|
.textTheme
|
||||||
.fontSize,
|
.labelSmall!
|
||||||
color: Theme.of(context)
|
.fontSize,
|
||||||
.colorScheme
|
color: Theme.of(context)
|
||||||
.outline),
|
.colorScheme
|
||||||
),
|
.outline),
|
||||||
const Spacer(),
|
),
|
||||||
if (_favDetailController
|
],
|
||||||
.item.value.attr !=
|
),
|
||||||
null)
|
|
||||||
Text(
|
|
||||||
'共${_favDetailController.item.value.mediaCount}条视频 · ${Utils.isPublicFavText(_favDetailController.item.value.attr ?? 0)}',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.labelSmall!
|
|
||||||
.fontSize,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Obx(() =>
|
||||||
Obx(() => _buildBody(_favDetailController.loadingState.value)),
|
_buildBody(_favDetailController.loadingState.value)),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -76,15 +76,19 @@ class _FollowPageState extends State<FollowPage> {
|
|||||||
if (data['status']) {
|
if (data['status']) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
SafeArea(
|
||||||
controller: _followController.tabController,
|
top: false,
|
||||||
isScrollable: true,
|
bottom: false,
|
||||||
tabAlignment: TabAlignment.start,
|
child: TabBar(
|
||||||
tabs: [
|
controller: _followController.tabController,
|
||||||
for (var i in data['data']) ...[
|
isScrollable: true,
|
||||||
Tab(text: i.name),
|
tabAlignment: TabAlignment.start,
|
||||||
]
|
tabs: [
|
||||||
],
|
for (var i in data['data']) ...[
|
||||||
|
Tab(text: i.name),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Material(
|
child: Material(
|
||||||
|
|||||||
@@ -92,12 +92,12 @@ class _FollowListState extends State<FollowList> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: errorWidget(
|
: scrollErrorWidget(
|
||||||
callback: () => widget.ctr.queryFollowings('init'),
|
callback: () => widget.ctr.queryFollowings('init'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return errorWidget(
|
return scrollErrorWidget(
|
||||||
errMsg: data['msg'],
|
errMsg: data['msg'],
|
||||||
callback: () => widget.ctr.queryFollowings('init'),
|
callback: () => widget.ctr.queryFollowings('init'),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ class _OwnerFollowListState extends State<OwnerFollowList>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: errorWidget(
|
: scrollErrorWidget(
|
||||||
callback: () => widget.ctr.queryFollowings('init'),
|
callback: () => widget.ctr.queryFollowings('init'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return errorWidget(
|
return scrollErrorWidget(
|
||||||
errMsg: data['msg'],
|
errMsg: data['msg'],
|
||||||
callback: () => widget.ctr.queryFollowings('init'),
|
callback: () => widget.ctr.queryFollowings('init'),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -182,26 +182,30 @@ class _HistoryPageState extends State<HistoryPage>
|
|||||||
? Column(
|
? Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
SafeArea(
|
||||||
controller: _historyController.tabController,
|
top: false,
|
||||||
onTap: (index) {
|
bottom: false,
|
||||||
if (_historyController
|
child: TabBar(
|
||||||
.tabController!.indexIsChanging.not) {
|
controller: _historyController.tabController,
|
||||||
currCtr().scrollController.animToTop();
|
onTap: (index) {
|
||||||
} else {
|
if (_historyController
|
||||||
if (enableMultiSelect) {
|
.tabController!.indexIsChanging.not) {
|
||||||
currCtr(_historyController
|
currCtr().scrollController.animToTop();
|
||||||
.tabController!.previousIndex)
|
} else {
|
||||||
.handleSelect();
|
if (enableMultiSelect) {
|
||||||
|
currCtr(_historyController
|
||||||
|
.tabController!.previousIndex)
|
||||||
|
.handleSelect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
tabs: [
|
||||||
tabs: [
|
Tab(text: '全部'),
|
||||||
Tab(text: '全部'),
|
..._historyController.tabs.map(
|
||||||
..._historyController.tabs.map(
|
(item) => Tab(text: item.name),
|
||||||
(item) => Tab(text: item.name),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Material(
|
child: Material(
|
||||||
@@ -229,16 +233,20 @@ class _HistoryPageState extends State<HistoryPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget get _buildPage => refreshIndicator(
|
Widget get _buildPage => SafeArea(
|
||||||
onRefresh: () async {
|
top: false,
|
||||||
await _historyController.onRefresh();
|
bottom: false,
|
||||||
},
|
child: refreshIndicator(
|
||||||
child: CustomScrollView(
|
onRefresh: () async {
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
await _historyController.onRefresh();
|
||||||
controller: _historyController.scrollController,
|
},
|
||||||
slivers: [
|
child: CustomScrollView(
|
||||||
Obx(() => _buildBody(_historyController.loadingState.value)),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
],
|
controller: _historyController.scrollController,
|
||||||
|
slivers: [
|
||||||
|
Obx(() => _buildBody(_historyController.loadingState.value)),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -337,239 +337,292 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
|||||||
const SizedBox(width: 6)
|
const SizedBox(width: 6)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Stack(
|
body: SafeArea(
|
||||||
children: [
|
top: false,
|
||||||
OrientationBuilder(
|
bottom: false,
|
||||||
builder: (context, orientation) {
|
child: Stack(
|
||||||
double padding = max(context.width / 2 - Grid.smallCardWidth, 0);
|
children: [
|
||||||
return Row(
|
OrientationBuilder(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
builder: (context, orientation) {
|
||||||
children: [
|
double padding =
|
||||||
Expanded(
|
max(context.width / 2 - Grid.smallCardWidth, 0);
|
||||||
flex: _ratio[0].toInt(),
|
return Row(
|
||||||
child: CustomScrollView(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
controller: _htmlRenderCtr.scrollController,
|
children: [
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
|
||||||
slivers: [
|
|
||||||
SliverPadding(
|
|
||||||
padding: orientation == Orientation.portrait
|
|
||||||
? EdgeInsets.symmetric(horizontal: padding)
|
|
||||||
: EdgeInsets.only(left: padding / 4),
|
|
||||||
sliver: SliverToBoxAdapter(
|
|
||||||
child: Obx(
|
|
||||||
() => _htmlRenderCtr.loaded.value
|
|
||||||
? _buildHeader
|
|
||||||
: const SizedBox(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverPadding(
|
|
||||||
padding: orientation == Orientation.portrait
|
|
||||||
? EdgeInsets.symmetric(horizontal: padding)
|
|
||||||
: EdgeInsets.only(
|
|
||||||
left: padding / 4,
|
|
||||||
bottom:
|
|
||||||
MediaQuery.paddingOf(context).bottom + 80,
|
|
||||||
),
|
|
||||||
sliver: _buildContent,
|
|
||||||
),
|
|
||||||
if (orientation == Orientation.portrait) ...[
|
|
||||||
SliverPadding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
|
||||||
sliver: SliverToBoxAdapter(
|
|
||||||
child: Divider(
|
|
||||||
thickness: 8,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.dividerColor
|
|
||||||
.withOpacity(0.05),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverPadding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
|
||||||
sliver: SliverToBoxAdapter(child: replyHeader()),
|
|
||||||
),
|
|
||||||
SliverPadding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
|
||||||
sliver: Obx(
|
|
||||||
() =>
|
|
||||||
replyList(_htmlRenderCtr.loadingState.value),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (orientation == Orientation.landscape) ...[
|
|
||||||
VerticalDivider(
|
|
||||||
thickness: 8,
|
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.05),
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: _ratio[1].toInt(),
|
flex: _ratio[0].toInt(),
|
||||||
child: Scaffold(
|
child: CustomScrollView(
|
||||||
key: _key,
|
controller: _htmlRenderCtr.scrollController,
|
||||||
backgroundColor: Colors.transparent,
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
body: refreshIndicator(
|
slivers: [
|
||||||
onRefresh: () async {
|
SliverPadding(
|
||||||
await _htmlRenderCtr.onRefresh();
|
padding: orientation == Orientation.portrait
|
||||||
},
|
? EdgeInsets.symmetric(horizontal: padding)
|
||||||
child: CustomScrollView(
|
: EdgeInsets.only(left: padding / 4),
|
||||||
controller: _htmlRenderCtr.scrollController,
|
sliver: SliverToBoxAdapter(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
child: Obx(
|
||||||
slivers: [
|
() => _htmlRenderCtr.loaded.value
|
||||||
SliverPadding(
|
? _buildHeader
|
||||||
padding: EdgeInsets.only(right: padding / 4),
|
: const SizedBox(),
|
||||||
sliver: SliverToBoxAdapter(
|
),
|
||||||
child: replyHeader(),
|
),
|
||||||
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding: orientation == Orientation.portrait
|
||||||
|
? EdgeInsets.symmetric(horizontal: padding)
|
||||||
|
: EdgeInsets.only(
|
||||||
|
left: padding / 4,
|
||||||
|
bottom:
|
||||||
|
MediaQuery.paddingOf(context).bottom +
|
||||||
|
80,
|
||||||
|
),
|
||||||
|
sliver: _buildContent,
|
||||||
|
),
|
||||||
|
if (orientation == Orientation.portrait) ...[
|
||||||
|
SliverPadding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: padding),
|
||||||
|
sliver: SliverToBoxAdapter(
|
||||||
|
child: Divider(
|
||||||
|
thickness: 8,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.dividerColor
|
||||||
|
.withOpacity(0.05),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverPadding(
|
),
|
||||||
padding: EdgeInsets.only(right: padding / 4),
|
SliverPadding(
|
||||||
sliver: Obx(
|
padding:
|
||||||
() => replyList(
|
EdgeInsets.symmetric(horizontal: padding),
|
||||||
_htmlRenderCtr.loadingState.value),
|
sliver: SliverToBoxAdapter(child: replyHeader()),
|
||||||
),
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: padding),
|
||||||
|
sliver: Obx(
|
||||||
|
() => replyList(
|
||||||
|
_htmlRenderCtr.loadingState.value),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (orientation == Orientation.landscape) ...[
|
||||||
|
VerticalDivider(
|
||||||
|
thickness: 8,
|
||||||
|
color: Theme.of(context).dividerColor.withOpacity(0.05),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: _ratio[1].toInt(),
|
||||||
|
child: Scaffold(
|
||||||
|
key: _key,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
body: refreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
await _htmlRenderCtr.onRefresh();
|
||||||
|
},
|
||||||
|
child: CustomScrollView(
|
||||||
|
controller: _htmlRenderCtr.scrollController,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
slivers: [
|
||||||
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(right: padding / 4),
|
||||||
|
sliver: SliverToBoxAdapter(
|
||||||
|
child: replyHeader(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(right: padding / 4),
|
||||||
|
sliver: Obx(
|
||||||
|
() => replyList(
|
||||||
|
_htmlRenderCtr.loadingState.value),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
],
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
Positioned(
|
||||||
Positioned(
|
left: 0,
|
||||||
left: 0,
|
right: 0,
|
||||||
right: 0,
|
bottom: 0,
|
||||||
bottom: 0,
|
child: SlideTransition(
|
||||||
child: SlideTransition(
|
position: Tween<Offset>(
|
||||||
position: Tween<Offset>(
|
begin: const Offset(0, 1),
|
||||||
begin: const Offset(0, 1),
|
end: const Offset(0, 0),
|
||||||
end: const Offset(0, 0),
|
).animate(CurvedAnimation(
|
||||||
).animate(CurvedAnimation(
|
parent: fabAnimationCtr,
|
||||||
parent: fabAnimationCtr,
|
curve: Curves.easeInOut,
|
||||||
curve: Curves.easeInOut,
|
)),
|
||||||
)),
|
child: Builder(
|
||||||
child: Builder(
|
builder: (context) {
|
||||||
builder: (context) {
|
Widget button() => FloatingActionButton(
|
||||||
Widget button() => FloatingActionButton(
|
heroTag: null,
|
||||||
heroTag: null,
|
onPressed: () {
|
||||||
onPressed: () {
|
feedBack();
|
||||||
feedBack();
|
_htmlRenderCtr.onReply(
|
||||||
_htmlRenderCtr.onReply(
|
context,
|
||||||
context,
|
oid: _htmlRenderCtr.oid.value,
|
||||||
oid: _htmlRenderCtr.oid.value,
|
replyType: ReplyType.values[type],
|
||||||
replyType: ReplyType.values[type],
|
);
|
||||||
);
|
},
|
||||||
},
|
tooltip: '评论动态',
|
||||||
tooltip: '评论动态',
|
child: const Icon(Icons.reply),
|
||||||
child: const Icon(Icons.reply),
|
);
|
||||||
);
|
return _htmlRenderCtr.showDynActionBar.not
|
||||||
return _htmlRenderCtr.showDynActionBar.not
|
? Align(
|
||||||
? Align(
|
alignment: Alignment.bottomRight,
|
||||||
alignment: Alignment.bottomRight,
|
child: Padding(
|
||||||
child: Padding(
|
padding: EdgeInsets.only(
|
||||||
padding: EdgeInsets.only(
|
right: 14,
|
||||||
right: 14,
|
bottom:
|
||||||
bottom:
|
MediaQuery.of(context).padding.bottom + 14,
|
||||||
MediaQuery.of(context).padding.bottom + 14,
|
|
||||||
),
|
|
||||||
child: button(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Obx(
|
|
||||||
() => Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
right: 14,
|
|
||||||
bottom: 14 +
|
|
||||||
(_htmlRenderCtr.item.value.idStr != null
|
|
||||||
? 0
|
|
||||||
: MediaQuery.of(context)
|
|
||||||
.padding
|
|
||||||
.bottom),
|
|
||||||
),
|
|
||||||
child: button(),
|
|
||||||
),
|
),
|
||||||
_htmlRenderCtr.item.value.idStr != null
|
child: button(),
|
||||||
? Container(
|
),
|
||||||
decoration: BoxDecoration(
|
)
|
||||||
color: Theme.of(context)
|
: Obx(
|
||||||
.colorScheme
|
() => Column(
|
||||||
.surface,
|
mainAxisSize: MainAxisSize.min,
|
||||||
border: Border(
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
top: BorderSide(
|
children: [
|
||||||
color: Theme.of(context)
|
Padding(
|
||||||
.colorScheme
|
padding: EdgeInsets.only(
|
||||||
.outline
|
right: 14,
|
||||||
.withOpacity(0.08),
|
bottom: 14 +
|
||||||
|
(_htmlRenderCtr.item.value.idStr != null
|
||||||
|
? 0
|
||||||
|
: MediaQuery.of(context)
|
||||||
|
.padding
|
||||||
|
.bottom),
|
||||||
|
),
|
||||||
|
child: button(),
|
||||||
|
),
|
||||||
|
_htmlRenderCtr.item.value.idStr != null
|
||||||
|
? Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.surface,
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline
|
||||||
|
.withOpacity(0.08),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
padding: EdgeInsets.only(
|
||||||
padding: EdgeInsets.only(
|
bottom:
|
||||||
bottom: MediaQuery.paddingOf(context)
|
MediaQuery.paddingOf(context)
|
||||||
.bottom),
|
.bottom),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.spaceAround,
|
MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (btnContext) =>
|
builder: (btnContext) =>
|
||||||
TextButton.icon(
|
TextButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useSafeArea: true,
|
useSafeArea: true,
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
RepostPanel(
|
RepostPanel(
|
||||||
item: _htmlRenderCtr
|
item: _htmlRenderCtr
|
||||||
.item.value,
|
.item.value,
|
||||||
callback: () {
|
callback: () {
|
||||||
int count = int.tryParse(
|
int count = int.tryParse(
|
||||||
_htmlRenderCtr
|
_htmlRenderCtr
|
||||||
.item
|
.item
|
||||||
.value
|
.value
|
||||||
.modules
|
.modules
|
||||||
?.moduleStat
|
?.moduleStat
|
||||||
?.forward
|
?.forward
|
||||||
?.count ??
|
?.count ??
|
||||||
'0') ??
|
'0') ??
|
||||||
0;
|
0;
|
||||||
_htmlRenderCtr
|
_htmlRenderCtr
|
||||||
|
.item
|
||||||
|
.value
|
||||||
|
.modules
|
||||||
|
?.moduleStat
|
||||||
|
?.forward!
|
||||||
|
.count =
|
||||||
|
(count + 1)
|
||||||
|
.toString();
|
||||||
|
if (btnContext
|
||||||
|
.mounted) {
|
||||||
|
(btnContext
|
||||||
|
as Element?)
|
||||||
|
?.markNeedsBuild();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
FontAwesomeIcons
|
||||||
|
.shareFromSquare,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline,
|
||||||
|
semanticLabel: "转发",
|
||||||
|
),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: const EdgeInsets
|
||||||
|
.fromLTRB(15, 0, 15, 0),
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
_htmlRenderCtr
|
||||||
.item
|
.item
|
||||||
.value
|
.value
|
||||||
.modules
|
.modules
|
||||||
?.moduleStat
|
?.moduleStat
|
||||||
?.forward!
|
?.forward!
|
||||||
.count =
|
.count !=
|
||||||
(count + 1)
|
null
|
||||||
.toString();
|
? Utils.numFormat(
|
||||||
if (btnContext
|
_htmlRenderCtr
|
||||||
.mounted) {
|
.item
|
||||||
(btnContext
|
.value
|
||||||
as Element?)
|
.modules
|
||||||
?.markNeedsBuild();
|
?.moduleStat
|
||||||
}
|
?.forward!
|
||||||
},
|
.count)
|
||||||
),
|
: '转发',
|
||||||
);
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TextButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
Utils.shareText(
|
||||||
|
'${HttpString.dynamicShareBaseUrl}/${_htmlRenderCtr.item.value.idStr}');
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
FontAwesomeIcons
|
FontAwesomeIcons.shareNodes,
|
||||||
.shareFromSquare,
|
|
||||||
size: 16,
|
size: 16,
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.outline,
|
.outline,
|
||||||
semanticLabel: "转发",
|
semanticLabel: "分享",
|
||||||
),
|
),
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
padding:
|
padding:
|
||||||
@@ -580,178 +633,134 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
|||||||
.colorScheme
|
.colorScheme
|
||||||
.outline,
|
.outline,
|
||||||
),
|
),
|
||||||
label: Text(
|
label: const Text('分享'),
|
||||||
_htmlRenderCtr
|
|
||||||
.item
|
|
||||||
.value
|
|
||||||
.modules
|
|
||||||
?.moduleStat
|
|
||||||
?.forward!
|
|
||||||
.count !=
|
|
||||||
null
|
|
||||||
? Utils.numFormat(
|
|
||||||
_htmlRenderCtr
|
|
||||||
.item
|
|
||||||
.value
|
|
||||||
.modules
|
|
||||||
?.moduleStat
|
|
||||||
?.forward!
|
|
||||||
.count)
|
|
||||||
: '转发',
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
child: Builder(
|
||||||
child: TextButton.icon(
|
builder: (context) =>
|
||||||
onPressed: () {
|
TextButton.icon(
|
||||||
Utils.shareText(
|
onPressed: () => RequestUtils
|
||||||
'${HttpString.dynamicShareBaseUrl}/${_htmlRenderCtr.item.value.idStr}');
|
.onLikeDynamic(
|
||||||
},
|
_htmlRenderCtr.item.value,
|
||||||
icon: Icon(
|
() {
|
||||||
FontAwesomeIcons.shareNodes,
|
if (context.mounted) {
|
||||||
size: 16,
|
(context as Element?)
|
||||||
color: Theme.of(context)
|
?.markNeedsBuild();
|
||||||
.colorScheme
|
}
|
||||||
.outline,
|
},
|
||||||
semanticLabel: "分享",
|
),
|
||||||
),
|
icon: Icon(
|
||||||
style: TextButton.styleFrom(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.fromLTRB(
|
|
||||||
15, 0, 15, 0),
|
|
||||||
foregroundColor:
|
|
||||||
Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline,
|
|
||||||
),
|
|
||||||
label: const Text('分享'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) =>
|
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () =>
|
|
||||||
RequestUtils.onLikeDynamic(
|
|
||||||
_htmlRenderCtr.item.value,
|
|
||||||
() {
|
|
||||||
if (context.mounted) {
|
|
||||||
(context as Element?)
|
|
||||||
?.markNeedsBuild();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
icon: Icon(
|
|
||||||
_htmlRenderCtr
|
|
||||||
.item
|
|
||||||
.value
|
|
||||||
.modules
|
|
||||||
?.moduleStat
|
|
||||||
?.like
|
|
||||||
?.status ==
|
|
||||||
true
|
|
||||||
? FontAwesomeIcons
|
|
||||||
.solidThumbsUp
|
|
||||||
: FontAwesomeIcons
|
|
||||||
.thumbsUp,
|
|
||||||
size: 16,
|
|
||||||
color: _htmlRenderCtr
|
|
||||||
.item
|
|
||||||
.value
|
|
||||||
.modules
|
|
||||||
?.moduleStat
|
|
||||||
?.like
|
|
||||||
?.status ==
|
|
||||||
true
|
|
||||||
? Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.primary
|
|
||||||
: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline,
|
|
||||||
semanticLabel: _htmlRenderCtr
|
|
||||||
.item
|
|
||||||
.value
|
|
||||||
.modules
|
|
||||||
?.moduleStat
|
|
||||||
?.like
|
|
||||||
?.status ==
|
|
||||||
true
|
|
||||||
? "已赞"
|
|
||||||
: "点赞",
|
|
||||||
),
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.fromLTRB(
|
|
||||||
15, 0, 15, 0),
|
|
||||||
foregroundColor:
|
|
||||||
Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline,
|
|
||||||
),
|
|
||||||
label: AnimatedSwitcher(
|
|
||||||
duration: const Duration(
|
|
||||||
milliseconds: 400),
|
|
||||||
transitionBuilder:
|
|
||||||
(Widget child,
|
|
||||||
Animation<double>
|
|
||||||
animation) {
|
|
||||||
return ScaleTransition(
|
|
||||||
scale: animation,
|
|
||||||
child: child);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
_htmlRenderCtr
|
_htmlRenderCtr
|
||||||
.item
|
.item
|
||||||
.value
|
.value
|
||||||
.modules
|
.modules
|
||||||
?.moduleStat
|
?.moduleStat
|
||||||
?.like
|
?.like
|
||||||
?.count !=
|
?.status ==
|
||||||
null
|
true
|
||||||
? Utils.numFormat(
|
? FontAwesomeIcons
|
||||||
_htmlRenderCtr
|
.solidThumbsUp
|
||||||
|
: FontAwesomeIcons
|
||||||
|
.thumbsUp,
|
||||||
|
size: 16,
|
||||||
|
color: _htmlRenderCtr
|
||||||
.item
|
.item
|
||||||
.value
|
.value
|
||||||
.modules!
|
.modules
|
||||||
.moduleStat!
|
?.moduleStat
|
||||||
.like!
|
?.like
|
||||||
.count)
|
?.status ==
|
||||||
: '点赞',
|
true
|
||||||
style: TextStyle(
|
? Theme.of(context)
|
||||||
color: _htmlRenderCtr
|
.colorScheme
|
||||||
|
.primary
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline,
|
||||||
|
semanticLabel:
|
||||||
|
_htmlRenderCtr
|
||||||
|
.item
|
||||||
|
.value
|
||||||
|
.modules
|
||||||
|
?.moduleStat
|
||||||
|
?.like
|
||||||
|
?.status ==
|
||||||
|
true
|
||||||
|
? "已赞"
|
||||||
|
: "点赞",
|
||||||
|
),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: const EdgeInsets
|
||||||
|
.fromLTRB(15, 0, 15, 0),
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline,
|
||||||
|
),
|
||||||
|
label: AnimatedSwitcher(
|
||||||
|
duration: const Duration(
|
||||||
|
milliseconds: 400),
|
||||||
|
transitionBuilder:
|
||||||
|
(Widget child,
|
||||||
|
Animation<double>
|
||||||
|
animation) {
|
||||||
|
return ScaleTransition(
|
||||||
|
scale: animation,
|
||||||
|
child: child);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
_htmlRenderCtr
|
||||||
.item
|
.item
|
||||||
.value
|
.value
|
||||||
.modules
|
.modules
|
||||||
?.moduleStat
|
?.moduleStat
|
||||||
?.like
|
?.like
|
||||||
?.status ==
|
?.count !=
|
||||||
true
|
null
|
||||||
? Theme.of(context)
|
? Utils.numFormat(
|
||||||
.colorScheme
|
_htmlRenderCtr
|
||||||
.primary
|
.item
|
||||||
: Theme.of(context)
|
.value
|
||||||
.colorScheme
|
.modules!
|
||||||
.outline,
|
.moduleStat!
|
||||||
|
.like!
|
||||||
|
.count)
|
||||||
|
: '点赞',
|
||||||
|
style: TextStyle(
|
||||||
|
color: _htmlRenderCtr
|
||||||
|
.item
|
||||||
|
.value
|
||||||
|
.modules
|
||||||
|
?.moduleStat
|
||||||
|
?.like
|
||||||
|
?.status ==
|
||||||
|
true
|
||||||
|
? Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primary
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
)
|
||||||
)
|
: const SizedBox.shrink(),
|
||||||
: const SizedBox.shrink(),
|
],
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,24 +88,28 @@ class _LaterPageState extends State<LaterPage>
|
|||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
SafeArea(
|
||||||
isScrollable: true,
|
top: false,
|
||||||
controller: _tabController,
|
bottom: false,
|
||||||
tabAlignment: TabAlignment.start,
|
child: TabBar(
|
||||||
tabs: LaterViewType.values.map((item) {
|
isScrollable: true,
|
||||||
final count = _baseCtr.counts[item];
|
controller: _tabController,
|
||||||
return Tab(
|
tabAlignment: TabAlignment.start,
|
||||||
text: '${item.title}${count != -1 ? '($count)' : ''}');
|
tabs: LaterViewType.values.map((item) {
|
||||||
}).toList(),
|
final count = _baseCtr.counts[item];
|
||||||
onTap: (_) {
|
return Tab(
|
||||||
if (_tabController.indexIsChanging.not) {
|
text: '${item.title}${count != -1 ? '($count)' : ''}');
|
||||||
currCtr().scrollController.animToTop();
|
}).toList(),
|
||||||
} else {
|
onTap: (_) {
|
||||||
if (_baseCtr.enableMultiSelect.value) {
|
if (_tabController.indexIsChanging.not) {
|
||||||
currCtr(_tabController.previousIndex).handleSelect();
|
currCtr().scrollController.animToTop();
|
||||||
|
} else {
|
||||||
|
if (_baseCtr.enableMultiSelect.value) {
|
||||||
|
currCtr(_tabController.previousIndex).handleSelect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
@@ -113,8 +117,13 @@ class _LaterPageState extends State<LaterPage>
|
|||||||
? const NeverScrollableScrollPhysics()
|
? const NeverScrollableScrollPhysics()
|
||||||
: const CustomTabBarViewScrollPhysics(),
|
: const CustomTabBarViewScrollPhysics(),
|
||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
children:
|
children: LaterViewType.values
|
||||||
LaterViewType.values.map((item) => item.page).toList(),
|
.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/chat.dart';
|
||||||
import 'package:PiliPlus/pages/live_room/widgets/header_control.dart';
|
import 'package:PiliPlus/pages/live_room/widgets/header_control.dart';
|
||||||
import 'package:PiliPlus/services/service_locator.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/page_utils.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
@@ -203,7 +204,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const SizedBox();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -228,9 +229,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
width: Get.width,
|
width: Get.width,
|
||||||
height: Get.height,
|
height: Get.height,
|
||||||
imageUrl: Utils.thumbnailImgUrl(
|
imageUrl: _liveRoomController.roomInfoH5.value
|
||||||
_liveRoomController.roomInfoH5.value.roomInfo!
|
.roomInfo!.appBackground!.http2https,
|
||||||
.appBackground!),
|
|
||||||
)
|
)
|
||||||
: Image.asset(
|
: Image.asset(
|
||||||
'assets/images/live/default_bg.webp',
|
'assets/images/live/default_bg.webp',
|
||||||
@@ -239,25 +239,31 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
isPortrait
|
SafeArea(
|
||||||
? Obx(
|
top: false,
|
||||||
() {
|
left: !isFullScreen,
|
||||||
if (_liveRoomController.isPortrait.value) {
|
right: !isFullScreen,
|
||||||
if (padding == null) {
|
bottom: false,
|
||||||
final padding = MediaQuery.paddingOf(context);
|
child: isPortrait
|
||||||
this.padding = padding.bottom + padding.top;
|
? Obx(
|
||||||
|
() {
|
||||||
|
if (_liveRoomController.isPortrait.value) {
|
||||||
|
if (padding == null) {
|
||||||
|
final padding = MediaQuery.paddingOf(context);
|
||||||
|
this.padding = padding.bottom + padding.top;
|
||||||
|
}
|
||||||
|
return _buildPP;
|
||||||
}
|
}
|
||||||
return _buildPP;
|
return _buildPH;
|
||||||
}
|
},
|
||||||
return _buildPH;
|
)
|
||||||
},
|
: Column(
|
||||||
)
|
children: [
|
||||||
: Column(
|
Obx(() => _buildAppBar),
|
||||||
children: [
|
_buildBodyH,
|
||||||
Obx(() => _buildAppBar),
|
],
|
||||||
_buildBodyH,
|
),
|
||||||
],
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -458,10 +464,13 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
children: [
|
children: [
|
||||||
Obx(
|
Obx(
|
||||||
() => Container(
|
() => Container(
|
||||||
|
margin:
|
||||||
|
EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom),
|
||||||
color: isFullScreen ? Colors.black : null,
|
color: isFullScreen ? Colors.black : null,
|
||||||
width: isFullScreen ? Get.size.width : videoWidth,
|
width: isFullScreen ? Get.size.width : videoWidth,
|
||||||
height: isFullScreen ? Get.size.height : Get.size.width * 9 / 16,
|
height: isFullScreen ? Get.size.height : Get.size.width * 9 / 16,
|
||||||
child: MediaQuery.removePadding(
|
child: MediaQuery.removePadding(
|
||||||
|
removeTop: true,
|
||||||
removeRight: true,
|
removeRight: true,
|
||||||
context: context,
|
context: context,
|
||||||
child: videoPlayerPanel(fill: Colors.transparent),
|
child: videoPlayerPanel(fill: Colors.transparent),
|
||||||
@@ -469,13 +478,9 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SafeArea(
|
child: Column(
|
||||||
left: false,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
top: false,
|
children: _buildBottomWidget,
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: _buildBottomWidget,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ class _MainAppState extends State<MainApp>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final bool isPortrait = context.orientation == Orientation.portrait;
|
||||||
return PopScope(
|
return PopScope(
|
||||||
canPop: false,
|
canPop: false,
|
||||||
onPopInvokedWithResult: (bool didPop, Object? result) async {
|
onPopInvokedWithResult: (bool didPop, Object? result) async {
|
||||||
@@ -200,8 +201,7 @@ class _MainAppState extends State<MainApp>
|
|||||||
body: Row(
|
body: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
if (useSideBar ||
|
if (useSideBar || !isPortrait) ...[
|
||||||
context.orientation == Orientation.landscape) ...[
|
|
||||||
Obx(
|
Obx(
|
||||||
() => _mainController.navigationBars.length > 1
|
() => _mainController.navigationBars.length > 1
|
||||||
? context.isTablet
|
? context.isTablet
|
||||||
@@ -298,26 +298,28 @@ class _MainAppState extends State<MainApp>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _mainController.mainTabBarView
|
child: SafeArea(
|
||||||
? CustomTabBarView(
|
top: false,
|
||||||
scrollDirection:
|
bottom: false,
|
||||||
context.orientation == Orientation.portrait
|
left: isPortrait,
|
||||||
? Axis.horizontal
|
child: _mainController.mainTabBarView
|
||||||
: Axis.vertical,
|
? CustomTabBarView(
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
scrollDirection:
|
||||||
controller: _mainController.controller,
|
isPortrait ? Axis.horizontal : Axis.vertical,
|
||||||
children: _mainController.pages,
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
)
|
controller: _mainController.controller,
|
||||||
: PageView(
|
children: _mainController.pages,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
)
|
||||||
controller: _mainController.controller,
|
: PageView(
|
||||||
children: _mainController.pages,
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
),
|
controller: _mainController.controller,
|
||||||
|
children: _mainController.pages,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
bottomNavigationBar: useSideBar ||
|
bottomNavigationBar: useSideBar || !isPortrait
|
||||||
context.orientation == Orientation.landscape
|
|
||||||
? null
|
? null
|
||||||
: StreamBuilder(
|
: StreamBuilder(
|
||||||
stream: _mainController.hideTabBar
|
stream: _mainController.hideTabBar
|
||||||
|
|||||||
@@ -40,63 +40,67 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
Color primary = Theme.of(context).colorScheme.primary;
|
Color primary = Theme.of(context).colorScheme.primary;
|
||||||
return Scaffold(
|
return MediaQuery.removePadding(
|
||||||
backgroundColor: Colors.transparent,
|
context: context,
|
||||||
appBar: AppBar(
|
removeLeft: context.orientation == Orientation.landscape,
|
||||||
toolbarHeight: 30,
|
child: Scaffold(
|
||||||
),
|
backgroundColor: Colors.transparent,
|
||||||
body: ListView(
|
appBar: AppBar(
|
||||||
controller: controller.scrollController,
|
toolbarHeight: 30,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
),
|
||||||
children: [
|
body: ListView(
|
||||||
ListTile(
|
controller: controller.scrollController,
|
||||||
leading: null,
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
title: Padding(
|
children: [
|
||||||
padding: const EdgeInsets.only(left: 20),
|
|
||||||
child: Text(
|
|
||||||
'媒体库',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: Theme.of(context).textTheme.titleLarge!.fontSize,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: IconButton(
|
|
||||||
tooltip: '设置',
|
|
||||||
onPressed: () {
|
|
||||||
Get.toNamed('/setting');
|
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.settings_outlined,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
for (var item in controller.list)
|
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: item['onTap'],
|
leading: null,
|
||||||
dense: true,
|
title: Padding(
|
||||||
leading: Padding(
|
padding: const EdgeInsets.only(left: 20),
|
||||||
padding: const EdgeInsets.only(left: 15),
|
child: Text(
|
||||||
child: Icon(
|
'媒体库',
|
||||||
item['icon'],
|
style: TextStyle(
|
||||||
color: primary,
|
fontSize: Theme.of(context).textTheme.titleLarge!.fontSize,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
contentPadding:
|
trailing: IconButton(
|
||||||
const EdgeInsets.only(left: 15, top: 2, bottom: 2),
|
tooltip: '设置',
|
||||||
minLeadingWidth: 0,
|
onPressed: () {
|
||||||
title: Text(
|
Get.toNamed('/setting');
|
||||||
item['title'],
|
},
|
||||||
style: const TextStyle(fontSize: 15),
|
icon: const Icon(
|
||||||
|
Icons.settings_outlined,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Obx(
|
for (var item in controller.list)
|
||||||
() => controller.loadingState.value is Loading
|
ListTile(
|
||||||
? const SizedBox.shrink()
|
onTap: item['onTap'],
|
||||||
: favFolder(),
|
dense: true,
|
||||||
)
|
leading: Padding(
|
||||||
],
|
padding: const EdgeInsets.only(left: 15),
|
||||||
|
child: Icon(
|
||||||
|
item['icon'],
|
||||||
|
color: primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding:
|
||||||
|
const EdgeInsets.only(left: 15, top: 2, bottom: 2),
|
||||||
|
minLeadingWidth: 0,
|
||||||
|
title: Text(
|
||||||
|
item['title'],
|
||||||
|
style: const TextStyle(fontSize: 15),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Obx(
|
||||||
|
() => controller.loadingState.value is Loading
|
||||||
|
? const SizedBox.shrink()
|
||||||
|
: favFolder(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class MemberControllerNew extends CommonDataController<Data, dynamic>
|
|||||||
late List<Tab> tabs;
|
late List<Tab> tabs;
|
||||||
List<Tab2>? tab2;
|
List<Tab2>? tab2;
|
||||||
RxInt contributeInitialIndex = 0.obs;
|
RxInt contributeInitialIndex = 0.obs;
|
||||||
double top = 0;
|
|
||||||
bool? hasSeasonOrSeries;
|
bool? hasSeasonOrSeries;
|
||||||
final fromViewAid = Get.parameters['from_view_aid'];
|
final fromViewAid = Get.parameters['from_view_aid'];
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
|||||||
late final String _heroTag;
|
late final String _heroTag;
|
||||||
late final MemberControllerNew _userController;
|
late final MemberControllerNew _userController;
|
||||||
final _key = GlobalKey<ExtendedNestedScrollViewState>();
|
final _key = GlobalKey<ExtendedNestedScrollViewState>();
|
||||||
|
int _offset = 120;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -45,8 +46,10 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void listener() {
|
void listener() {
|
||||||
_userController.showUname.value =
|
if (_userController.scrollController.hasClients) {
|
||||||
_userController.scrollController.offset >= 120;
|
_userController.showUname.value =
|
||||||
|
_userController.scrollController.offset >= _offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -57,11 +60,99 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (_userController.top == 0) {
|
|
||||||
_userController.top = MediaQuery.of(context).padding.top;
|
|
||||||
}
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
extendBody: true,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
resizeToAvoidBottomInset: false,
|
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) => <PopupMenuEntry>[
|
||||||
|
if (_userController.ownerMid != _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
|
||||||
|
? '加入黑名单'
|
||||||
|
: '移除黑名单'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () => _userController.shareUser(),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.share_outlined, size: 19),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(_userController.ownerMid != _mid ? '分享UP主' : '分享我的主页'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_userController.ownerMid != null &&
|
||||||
|
_userController.mid != _userController.ownerMid) ...[
|
||||||
|
const PopupMenuDivider(),
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
clipBehavior: Clip.hardEdge,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
content: ReportPanel(
|
||||||
|
name: _userController.username,
|
||||||
|
mid: _mid,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.error_outline,
|
||||||
|
size: 19,
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(
|
||||||
|
'举报',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.error),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
],
|
||||||
|
),
|
||||||
body: Obx(
|
body: Obx(
|
||||||
() => _userController.loadingState.value is Success
|
() => _userController.loadingState.value is Success
|
||||||
? LayoutBuilder(
|
? LayoutBuilder(
|
||||||
@@ -70,31 +161,24 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
|||||||
key: _key,
|
key: _key,
|
||||||
controller: _userController.scrollController,
|
controller: _userController.scrollController,
|
||||||
onlyOneScrollInBody: true,
|
onlyOneScrollInBody: true,
|
||||||
|
pinnedHeaderSliverHeightBuilder: () {
|
||||||
|
return kToolbarHeight +
|
||||||
|
MediaQuery.paddingOf(this.context).top.toInt();
|
||||||
|
},
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||||
return [
|
return [
|
||||||
SliverOverlapAbsorber(
|
_buildAppBar(
|
||||||
handle: ExtendedNestedScrollView
|
isV: constraints.maxHeight > constraints.maxWidth,
|
||||||
.sliverOverlapAbsorberHandleFor(context),
|
|
||||||
sliver: _buildAppBar(
|
|
||||||
isV: constraints.maxHeight > constraints.maxWidth,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
body: _userController.tab2?.isNotEmpty == true
|
body: _userController.tab2?.isNotEmpty == true
|
||||||
? LayoutBuilder(
|
? Column(
|
||||||
builder: (context, _) {
|
children: [
|
||||||
return Padding(
|
if ((_userController.tab2?.length ?? 0) > 1)
|
||||||
padding: EdgeInsets.only(
|
_buildTab,
|
||||||
top: ExtendedNestedScrollView
|
Expanded(child: _buildBody),
|
||||||
.sliverOverlapAbsorberHandleFor(
|
],
|
||||||
context)
|
|
||||||
.layoutExtent ??
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
child: _buildBody,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
: Center(child: const Text('EMPTY')),
|
: Center(child: const Text('EMPTY')),
|
||||||
);
|
);
|
||||||
@@ -109,14 +193,18 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
|||||||
|
|
||||||
Widget get _buildTab => Material(
|
Widget get _buildTab => Material(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: TabBar(
|
child: SafeArea(
|
||||||
controller: _userController.tabController,
|
top: false,
|
||||||
tabs: _userController.tabs,
|
bottom: false,
|
||||||
onTap: (value) {
|
child: TabBar(
|
||||||
if (_userController.tabController?.indexIsChanging == false) {
|
controller: _userController.tabController,
|
||||||
_key.currentState?.outerController.animToTop();
|
tabs: _userController.tabs,
|
||||||
}
|
onTap: (value) {
|
||||||
},
|
if (_userController.tabController?.indexIsChanging == false) {
|
||||||
|
_key.currentState?.outerController.animToTop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -150,119 +238,19 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildAppBar({bool needTab = true, bool isV = true}) =>
|
Widget _buildAppBar({bool isV = true}) {
|
||||||
DynamicSliverAppBar(
|
return DynamicSliverAppBar(
|
||||||
primary: false,
|
pinned: true,
|
||||||
leading: Padding(
|
primary: false,
|
||||||
padding: EdgeInsets.only(top: _userController.top),
|
automaticallyImplyLeading: false,
|
||||||
child: const BackButton(),
|
toolbarHeight: kToolbarHeight + MediaQuery.paddingOf(context).top,
|
||||||
),
|
flexibleSpace: _buildUserInfo(_userController.loadingState.value, isV),
|
||||||
hasTabBar: (_userController.tab2?.length ?? 0) > 1,
|
callback: (value) {
|
||||||
toolbarHeight: kToolbarHeight + _userController.top,
|
_offset = (value - 56 - MediaQuery.paddingOf(context).top).toInt();
|
||||||
title: IgnorePointer(
|
listener();
|
||||||
child: Obx(() => _userController.showUname.value &&
|
},
|
||||||
_userController.username != null
|
);
|
||||||
? Padding(
|
}
|
||||||
padding: EdgeInsets.only(top: _userController.top),
|
|
||||||
child: 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(
|
|
||||||
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(
|
|
||||||
icon: const Icon(Icons.more_vert),
|
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
|
||||||
if (_userController.ownerMid != _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
|
|
||||||
? '加入黑名单'
|
|
||||||
: '移除黑名单'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
PopupMenuItem(
|
|
||||||
onTap: () => _userController.shareUser(),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.share_outlined, size: 19),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Text(_userController.ownerMid != _mid
|
|
||||||
? '分享UP主'
|
|
||||||
: '分享我的主页'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (_userController.ownerMid != null &&
|
|
||||||
_userController.mid != _userController.ownerMid) ...[
|
|
||||||
const PopupMenuDivider(),
|
|
||||||
PopupMenuItem(
|
|
||||||
onTap: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
clipBehavior: Clip.hardEdge,
|
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 20,
|
|
||||||
vertical: 16,
|
|
||||||
),
|
|
||||||
content: ReportPanel(
|
|
||||||
name: _userController.username,
|
|
||||||
mid: _mid,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.error_outline,
|
|
||||||
size: 19,
|
|
||||||
color: Theme.of(context).colorScheme.error,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Text(
|
|
||||||
'举报',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.error),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _errorWidget(msg) {
|
Widget _errorWidget(msg) {
|
||||||
return errorWidget(
|
return errorWidget(
|
||||||
|
|||||||
@@ -118,6 +118,12 @@ class UserInfoCard extends StatelessWidget {
|
|||||||
onTap: () => Utils.copyText(card.name!),
|
onTap: () => Utils.copyText(card.name!),
|
||||||
child: Text(
|
child: Text(
|
||||||
card.name!,
|
card.name!,
|
||||||
|
strutStyle: StrutStyle(
|
||||||
|
height: 1,
|
||||||
|
leading: 0,
|
||||||
|
fontSize: 17,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
height: 1,
|
height: 1,
|
||||||
fontSize: 17,
|
fontSize: 17,
|
||||||
@@ -136,8 +142,7 @@ class UserInfoCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
if (card.vip?.vipStatus == 1)
|
if (card.vip?.vipStatus == 1)
|
||||||
CachedNetworkImage(
|
CachedNetworkImage(
|
||||||
imageUrl:
|
imageUrl: Utils.thumbnailImgUrl(card.vip!.label!.image!, 80),
|
||||||
Utils.thumbnailImgUrl(card.vip!.label!.image!.http2https),
|
|
||||||
height: 20,
|
height: 20,
|
||||||
placeholder: (context, url) {
|
placeholder: (context, url) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -612,7 +617,10 @@ class UserInfoCard extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildHeader(context),
|
// _buildHeader(context),
|
||||||
|
SizedBox(
|
||||||
|
height: Get.mediaQuery.padding.bottom + 56,
|
||||||
|
),
|
||||||
SafeArea(
|
SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
|
|||||||
@@ -39,18 +39,22 @@ class _MemberCoinPageState extends State<MemberCoinPage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('${widget.mid == _ownerMid ? '我' : '${widget.name}'}的最近投币'),
|
title: Text('${widget.mid == _ownerMid ? '我' : '${widget.name}'}的最近投币'),
|
||||||
),
|
),
|
||||||
body: CustomScrollView(
|
body: SafeArea(
|
||||||
slivers: [
|
top: false,
|
||||||
SliverPadding(
|
bottom: false,
|
||||||
padding: EdgeInsets.only(
|
child: CustomScrollView(
|
||||||
top: StyleString.safeSpace - 5,
|
slivers: [
|
||||||
left: StyleString.safeSpace,
|
SliverPadding(
|
||||||
right: StyleString.safeSpace,
|
padding: EdgeInsets.only(
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
top: StyleString.safeSpace - 5,
|
||||||
|
left: StyleString.safeSpace,
|
||||||
|
right: StyleString.safeSpace,
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
|
),
|
||||||
|
sliver: Obx(() => _buildBody(_ctr.loadingState.value)),
|
||||||
),
|
),
|
||||||
sliver: Obx(() => _buildBody(_ctr.loadingState.value)),
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,18 +39,22 @@ class _MemberLikePageState extends State<MemberLikePage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('${widget.mid == _ownerMid ? '我' : '${widget.name}'}的推荐'),
|
title: Text('${widget.mid == _ownerMid ? '我' : '${widget.name}'}的推荐'),
|
||||||
),
|
),
|
||||||
body: CustomScrollView(
|
body: SafeArea(
|
||||||
slivers: [
|
top: false,
|
||||||
SliverPadding(
|
bottom: false,
|
||||||
padding: EdgeInsets.only(
|
child: CustomScrollView(
|
||||||
top: StyleString.safeSpace - 5,
|
slivers: [
|
||||||
left: StyleString.safeSpace,
|
SliverPadding(
|
||||||
right: StyleString.safeSpace,
|
padding: EdgeInsets.only(
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
top: StyleString.safeSpace - 5,
|
||||||
|
left: StyleString.safeSpace,
|
||||||
|
right: StyleString.safeSpace,
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
|
),
|
||||||
|
sliver: Obx(() => _buildBody(_ctr.loadingState.value)),
|
||||||
),
|
),
|
||||||
sliver: Obx(() => _buildBody(_ctr.loadingState.value)),
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,22 +28,26 @@ class _SearchArchiveState extends State<SearchArchive>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return refreshIndicator(
|
return SafeArea(
|
||||||
onRefresh: () async {
|
top: false,
|
||||||
await widget.ctr.refreshArchive();
|
bottom: false,
|
||||||
},
|
child: refreshIndicator(
|
||||||
child: CustomScrollView(
|
onRefresh: () async {
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
await widget.ctr.refreshArchive();
|
||||||
slivers: [
|
},
|
||||||
SliverPadding(
|
child: CustomScrollView(
|
||||||
padding: EdgeInsets.only(
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
top: StyleString.safeSpace - 5,
|
slivers: [
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
SliverPadding(
|
||||||
),
|
padding: EdgeInsets.only(
|
||||||
sliver:
|
top: StyleString.safeSpace - 5,
|
||||||
Obx(() => _buildBody(context, widget.ctr.archiveState.value)),
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
)
|
),
|
||||||
],
|
sliver:
|
||||||
|
Obx(() => _buildBody(context, widget.ctr.archiveState.value)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,21 +30,25 @@ class _SearchDynamicState extends State<SearchDynamic>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return refreshIndicator(
|
return SafeArea(
|
||||||
onRefresh: () async {
|
top: false,
|
||||||
await widget.ctr.refreshDynamic();
|
bottom: false,
|
||||||
},
|
child: refreshIndicator(
|
||||||
child: CustomScrollView(
|
onRefresh: () async {
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
await widget.ctr.refreshDynamic();
|
||||||
slivers: [
|
},
|
||||||
SliverPadding(
|
child: CustomScrollView(
|
||||||
padding: EdgeInsets.only(
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
slivers: [
|
||||||
),
|
SliverPadding(
|
||||||
sliver:
|
padding: EdgeInsets.only(
|
||||||
Obx(() => _buildBody(context, widget.ctr.dynamicState.value)),
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
)
|
),
|
||||||
],
|
sliver:
|
||||||
|
Obx(() => _buildBody(context, widget.ctr.dynamicState.value)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,22 +55,26 @@ class _MemberSearchPageState extends State<MemberSearchPage> {
|
|||||||
() => _memberSearchCtr.hasData.value
|
() => _memberSearchCtr.hasData.value
|
||||||
? Column(
|
? Column(
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
SafeArea(
|
||||||
controller: _memberSearchCtr.tabController,
|
top: false,
|
||||||
tabs: [
|
bottom: false,
|
||||||
Obx(
|
child: TabBar(
|
||||||
() => Tab(
|
controller: _memberSearchCtr.tabController,
|
||||||
text:
|
tabs: [
|
||||||
'视频 ${_memberSearchCtr.archiveCount.value != -1 ? '${_memberSearchCtr.archiveCount.value}' : ''}',
|
Obx(
|
||||||
|
() => Tab(
|
||||||
|
text:
|
||||||
|
'视频 ${_memberSearchCtr.archiveCount.value != -1 ? '${_memberSearchCtr.archiveCount.value}' : ''}',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Obx(
|
||||||
Obx(
|
() => Tab(
|
||||||
() => Tab(
|
text:
|
||||||
text:
|
'动态 ${_memberSearchCtr.dynamicCount.value != -1 ? '${_memberSearchCtr.dynamicCount.value}' : ''}',
|
||||||
'动态 ${_memberSearchCtr.dynamicCount.value != -1 ? '${_memberSearchCtr.dynamicCount.value}' : ''}',
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: tabBarView(
|
child: tabBarView(
|
||||||
|
|||||||
@@ -52,220 +52,230 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('选择应用主题')),
|
appBar: AppBar(title: const Text('选择应用主题')),
|
||||||
body: ListView(
|
body: SafeArea(
|
||||||
children: [
|
bottom: false,
|
||||||
ListTile(
|
child: ListView(
|
||||||
onTap: () async {
|
children: [
|
||||||
ThemeType? result = await showDialog(
|
ListTile(
|
||||||
context: context,
|
onTap: () async {
|
||||||
builder: (context) {
|
ThemeType? result = await showDialog(
|
||||||
return SelectDialog<ThemeType>(
|
context: context,
|
||||||
title: '主题模式',
|
builder: (context) {
|
||||||
value: ctr.themeType.value,
|
return SelectDialog<ThemeType>(
|
||||||
values: ThemeType.values
|
title: '主题模式',
|
||||||
.map((e) => (e, e.description))
|
value: ctr.themeType.value,
|
||||||
.toList());
|
values: ThemeType.values
|
||||||
},
|
.map((e) => (e, e.description))
|
||||||
);
|
.toList());
|
||||||
if (result != null) {
|
},
|
||||||
try {
|
);
|
||||||
Get.find<MineController>().themeType.value = result;
|
if (result != null) {
|
||||||
} catch (_) {}
|
try {
|
||||||
ctr.themeType.value = result;
|
Get.find<MineController>().themeType.value = result;
|
||||||
GStorage.setting.put(SettingBoxKey.themeMode, result.index);
|
} catch (_) {}
|
||||||
Get.changeThemeMode(result.toThemeMode);
|
ctr.themeType.value = result;
|
||||||
}
|
GStorage.setting.put(SettingBoxKey.themeMode, result.index);
|
||||||
},
|
Get.changeThemeMode(result.toThemeMode);
|
||||||
leading: Container(
|
}
|
||||||
width: 40,
|
},
|
||||||
alignment: Alignment.center,
|
leading: Container(
|
||||||
child: const Icon(Icons.flashlight_on_outlined),
|
width: 40,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const Icon(Icons.flashlight_on_outlined),
|
||||||
|
),
|
||||||
|
title: Text('主题模式', style: titleStyle),
|
||||||
|
subtitle: Obx(() => Text(
|
||||||
|
'当前模式:${ctr.themeType.value.description}',
|
||||||
|
style: subTitleStyle)),
|
||||||
),
|
),
|
||||||
title: Text('主题模式', style: titleStyle),
|
Obx(
|
||||||
subtitle: Obx(() => Text('当前模式:${ctr.themeType.value.description}',
|
() => ListTile(
|
||||||
style: subTitleStyle)),
|
enabled: ctr.type.value != 0,
|
||||||
),
|
title: Row(
|
||||||
Obx(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
() => ListTile(
|
children: [
|
||||||
enabled: ctr.type.value != 0,
|
const Text('调色板风格'),
|
||||||
title: Row(
|
PopupMenuButton(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
enabled: ctr.type.value != 0,
|
||||||
children: [
|
initialValue: _dynamicSchemeVariant,
|
||||||
const Text('调色板风格'),
|
onSelected: (item) async {
|
||||||
PopupMenuButton(
|
_dynamicSchemeVariant = item;
|
||||||
enabled: ctr.type.value != 0,
|
await GStorage.setting
|
||||||
initialValue: _dynamicSchemeVariant,
|
.put(SettingBoxKey.schemeVariant, item.index);
|
||||||
onSelected: (item) async {
|
Get.forceAppUpdate();
|
||||||
_dynamicSchemeVariant = item;
|
},
|
||||||
await GStorage.setting
|
itemBuilder: (context) => FlexSchemeVariant.values
|
||||||
.put(SettingBoxKey.schemeVariant, item.index);
|
.map((item) => PopupMenuItem<FlexSchemeVariant>(
|
||||||
Get.forceAppUpdate();
|
value: item,
|
||||||
},
|
child: Text(item.variantName),
|
||||||
itemBuilder: (context) => FlexSchemeVariant.values
|
))
|
||||||
.map((item) => PopupMenuItem<FlexSchemeVariant>(
|
.toList(),
|
||||||
value: item,
|
child: Row(
|
||||||
child: Text(item.variantName),
|
mainAxisSize: MainAxisSize.min,
|
||||||
))
|
children: [
|
||||||
.toList(),
|
Text(
|
||||||
child: Row(
|
_dynamicSchemeVariant.variantName,
|
||||||
mainAxisSize: MainAxisSize.min,
|
style: TextStyle(
|
||||||
children: [
|
height: 1,
|
||||||
Text(
|
fontSize: 13,
|
||||||
_dynamicSchemeVariant.variantName,
|
color: ctr.type.value == 0
|
||||||
style: TextStyle(
|
? Theme.of(context)
|
||||||
height: 1,
|
.colorScheme
|
||||||
fontSize: 13,
|
.outline
|
||||||
|
.withOpacity(0.8)
|
||||||
|
: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
size: 20,
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
color: ctr.type.value == 0
|
color: ctr.type.value == 0
|
||||||
? Theme.of(context)
|
? Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.outline
|
.outline
|
||||||
.withOpacity(0.8)
|
.withOpacity(0.8)
|
||||||
: Theme.of(context).colorScheme.secondary,
|
: Theme.of(context).colorScheme.secondary,
|
||||||
),
|
)
|
||||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
],
|
||||||
),
|
),
|
||||||
Icon(
|
),
|
||||||
size: 20,
|
],
|
||||||
Icons.keyboard_arrow_right,
|
),
|
||||||
color: ctr.type.value == 0
|
leading: Container(
|
||||||
? Theme.of(context)
|
width: 40,
|
||||||
.colorScheme
|
alignment: Alignment.center,
|
||||||
.outline
|
child: Icon(Icons.palette_outlined),
|
||||||
.withOpacity(0.8)
|
),
|
||||||
: Theme.of(context).colorScheme.secondary,
|
subtitle: Text(
|
||||||
|
_dynamicSchemeVariant.description,
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Obx(
|
||||||
|
() => RadioListTile(
|
||||||
|
value: 0,
|
||||||
|
title: const Text('动态取色'),
|
||||||
|
groupValue: ctr.type.value,
|
||||||
|
onChanged: (dynamic val) async {
|
||||||
|
ctr.type.value = 0;
|
||||||
|
ctr.setting.put(SettingBoxKey.dynamicColor, true);
|
||||||
|
Get.forceAppUpdate();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Obx(
|
||||||
|
() => RadioListTile(
|
||||||
|
value: 1,
|
||||||
|
title: const Text('指定颜色'),
|
||||||
|
groupValue: ctr.type.value,
|
||||||
|
onChanged: (dynamic val) async {
|
||||||
|
ctr.type.value = 1;
|
||||||
|
ctr.setting.put(SettingBoxKey.dynamicColor, false);
|
||||||
|
Get.forceAppUpdate();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AnimatedSize(
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Obx(
|
||||||
|
() => SizedBox(
|
||||||
|
height: ctr.type.value == 0 ? 0 : null,
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(top: 12, left: 12, right: 12),
|
||||||
|
child: Wrap(
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
spacing: 22,
|
||||||
|
runSpacing: 18,
|
||||||
|
children: [
|
||||||
|
...ctr.colorThemes.map(
|
||||||
|
(e) {
|
||||||
|
final index = ctr.colorThemes.indexOf(e);
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
ctr.currentColor.value = index;
|
||||||
|
ctr.setting
|
||||||
|
.put(SettingBoxKey.customColor, index);
|
||||||
|
Get.forceAppUpdate();
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 46,
|
||||||
|
height: 46,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: e['color'].withOpacity(0.8),
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
border: Border.all(
|
||||||
|
width: 2,
|
||||||
|
color: ctr.currentColor.value == index
|
||||||
|
? Colors.black
|
||||||
|
: e['color'].withOpacity(0.8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
opacity: ctr.currentColor.value == index
|
||||||
|
? 1
|
||||||
|
: 0,
|
||||||
|
duration:
|
||||||
|
const Duration(milliseconds: 200),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.done,
|
||||||
|
color: Colors.black,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 3),
|
||||||
|
Text(
|
||||||
|
e['label'],
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: ctr.currentColor.value != index
|
||||||
|
? Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
leading: Container(
|
|
||||||
width: 40,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Icon(Icons.palette_outlined),
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
_dynamicSchemeVariant.description,
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Obx(
|
|
||||||
() => RadioListTile(
|
|
||||||
value: 0,
|
|
||||||
title: const Text('动态取色'),
|
|
||||||
groupValue: ctr.type.value,
|
|
||||||
onChanged: (dynamic val) async {
|
|
||||||
ctr.type.value = 0;
|
|
||||||
ctr.setting.put(SettingBoxKey.dynamicColor, true);
|
|
||||||
Get.forceAppUpdate();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Obx(
|
|
||||||
() => RadioListTile(
|
|
||||||
value: 1,
|
|
||||||
title: const Text('指定颜色'),
|
|
||||||
groupValue: ctr.type.value,
|
|
||||||
onChanged: (dynamic val) async {
|
|
||||||
ctr.type.value = 1;
|
|
||||||
ctr.setting.put(SettingBoxKey.dynamicColor, false);
|
|
||||||
Get.forceAppUpdate();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
AnimatedSize(
|
|
||||||
curve: Curves.easeInOut,
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
child: Obx(
|
|
||||||
() => SizedBox(
|
|
||||||
height: ctr.type.value == 0 ? 0 : null,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 12, left: 12, right: 12),
|
|
||||||
child: Wrap(
|
|
||||||
alignment: WrapAlignment.center,
|
|
||||||
spacing: 22,
|
|
||||||
runSpacing: 18,
|
|
||||||
children: [
|
|
||||||
...ctr.colorThemes.map(
|
|
||||||
(e) {
|
|
||||||
final index = ctr.colorThemes.indexOf(e);
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
ctr.currentColor.value = index;
|
|
||||||
ctr.setting.put(SettingBoxKey.customColor, index);
|
|
||||||
Get.forceAppUpdate();
|
|
||||||
},
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 46,
|
|
||||||
height: 46,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: e['color'].withOpacity(0.8),
|
|
||||||
borderRadius: BorderRadius.circular(50),
|
|
||||||
border: Border.all(
|
|
||||||
width: 2,
|
|
||||||
color: ctr.currentColor.value == index
|
|
||||||
? Colors.black
|
|
||||||
: e['color'].withOpacity(0.8),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: AnimatedOpacity(
|
|
||||||
opacity:
|
|
||||||
ctr.currentColor.value == index ? 1 : 0,
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.done,
|
|
||||||
color: Colors.black,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 3),
|
|
||||||
Text(
|
|
||||||
e['label'],
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: ctr.currentColor.value != index
|
|
||||||
? Theme.of(context).colorScheme.outline
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
...[
|
||||||
...[
|
IgnorePointer(
|
||||||
IgnorePointer(
|
child: SizedBox(
|
||||||
child: SizedBox(
|
height: Get.height / 2,
|
||||||
height: Get.height / 2,
|
width: Get.width,
|
||||||
width: Get.width,
|
child: const HomePage(),
|
||||||
child: const HomePage(),
|
),
|
||||||
),
|
),
|
||||||
),
|
IgnorePointer(
|
||||||
IgnorePointer(
|
child: NavigationBar(
|
||||||
child: NavigationBar(
|
destinations: defaultNavigationBars
|
||||||
destinations: defaultNavigationBars
|
.map(
|
||||||
.map(
|
(item) => NavigationDestination(
|
||||||
(item) => NavigationDestination(
|
icon: item['icon'],
|
||||||
icon: item['icon'],
|
label: item['label'],
|
||||||
label: item['label'],
|
),
|
||||||
),
|
)
|
||||||
)
|
.toList(),
|
||||||
.toList(),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,58 +48,55 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
|||||||
const SizedBox(width: 12)
|
const SizedBox(width: 12)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Column(
|
body: SafeArea(
|
||||||
children: [
|
child: Column(
|
||||||
Expanded(
|
children: [
|
||||||
child: Center(
|
Expanded(
|
||||||
child: Text(
|
child: Center(
|
||||||
'当前字体大小:${currentSize == 1.0 ? '默认' : currentSize}',
|
child: Text(
|
||||||
style: TextStyle(fontSize: 14 * currentSize),
|
'当前字体大小:${currentSize == 1.0 ? '默认' : currentSize}',
|
||||||
|
style: TextStyle(fontSize: 14 * currentSize),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
Container(
|
width: double.infinity,
|
||||||
width: double.infinity,
|
padding: EdgeInsets.all(20),
|
||||||
padding: EdgeInsets.only(
|
decoration: BoxDecoration(
|
||||||
left: 20,
|
border: Border(
|
||||||
right: 20,
|
top: BorderSide(
|
||||||
top: 20,
|
color: Theme.of(context)
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 20,
|
.colorScheme
|
||||||
),
|
.primary
|
||||||
decoration: BoxDecoration(
|
.withOpacity(0.3))),
|
||||||
border: Border(
|
color: Theme.of(context).colorScheme.surface,
|
||||||
top: BorderSide(
|
),
|
||||||
color: Theme.of(context)
|
child: Row(
|
||||||
.colorScheme
|
children: [
|
||||||
.primary
|
const Text('小'),
|
||||||
.withOpacity(0.3))),
|
Expanded(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
child: Slider(
|
||||||
),
|
min: minSize,
|
||||||
child: Row(
|
value: currentSize,
|
||||||
children: [
|
max: maxSize,
|
||||||
const Text('小'),
|
divisions: list.length - 1,
|
||||||
Expanded(
|
secondaryTrackValue: 1,
|
||||||
child: Slider(
|
onChanged: (double val) {
|
||||||
min: minSize,
|
currentSize = val.toPrecision(2);
|
||||||
value: currentSize,
|
setState(() {});
|
||||||
max: maxSize,
|
},
|
||||||
divisions: list.length - 1,
|
),
|
||||||
secondaryTrackValue: 1,
|
|
||||||
onChanged: (double val) {
|
|
||||||
currentSize = val.toPrecision(2);
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 5),
|
||||||
const SizedBox(width: 5),
|
const Text(
|
||||||
const Text(
|
'大',
|
||||||
'大',
|
style: TextStyle(fontSize: 20),
|
||||||
style: TextStyle(fontSize: 20),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,62 +144,79 @@ class _LogsPageState extends State<LogsPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: logsContent.isNotEmpty
|
body: logsContent.isNotEmpty
|
||||||
? ListView.builder(
|
? SafeArea(
|
||||||
itemCount: logsContent.length,
|
bottom: false,
|
||||||
itemBuilder: (context, index) {
|
child: ListView.separated(
|
||||||
final log = logsContent[index];
|
itemCount: logsContent.length,
|
||||||
if (log['date'] is DateTime) {
|
itemBuilder: (context, index) {
|
||||||
latestLog ??= log['date'];
|
final log = logsContent[index];
|
||||||
}
|
if (log['date'] is DateTime) {
|
||||||
return Column(
|
latestLog ??= log['date'];
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
}
|
||||||
mainAxisSize: MainAxisSize.min,
|
return Padding(
|
||||||
children: [
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
Row(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Row(
|
||||||
padding: const EdgeInsets.all(8.0),
|
children: [
|
||||||
child: Text(
|
Text(
|
||||||
log['date'].toString(),
|
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);
|
||||||
|
if (context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'已将 ${log['date'].toString()} 复制至剪贴板',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.copy_outlined, size: 16),
|
||||||
|
label: const Text('复制'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Card(
|
||||||
|
elevation: 1,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: SelectableText(log['body']),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () async {
|
|
||||||
await Utils.copyText('```\n${log['body']}\n```',
|
|
||||||
needToast: false);
|
|
||||||
if (context.mounted) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
'已将 ${log['date'].toString()} 复制至剪贴板',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.copy_outlined, size: 16),
|
|
||||||
label: const Text('复制'),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
);
|
||||||
padding: const EdgeInsets.all(8.0),
|
},
|
||||||
child: Card(
|
separatorBuilder: (context, index) => const Divider(
|
||||||
elevation: 1,
|
indent: 12,
|
||||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
endIndent: 12,
|
||||||
child: Padding(
|
height: 24,
|
||||||
padding: const EdgeInsets.all(12.0),
|
),
|
||||||
child: SelectableText(log['body']),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(indent: 12, endIndent: 12),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
: errorWidget(),
|
: scrollErrorWidget(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,9 +210,9 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
|||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SafeArea(
|
||||||
child: Column(
|
bottom: false,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding:
|
padding:
|
||||||
|
|||||||
@@ -75,24 +75,27 @@ class _SettingsSearchPageState extends State<SettingsSearchPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: Obx(
|
body: SafeArea(
|
||||||
() => _list.isEmpty
|
bottom: false,
|
||||||
? CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [HttpError()],
|
slivers: [
|
||||||
)
|
Obx(
|
||||||
: CustomScrollView(
|
() => _list.isEmpty
|
||||||
slivers: [
|
? HttpError()
|
||||||
SliverWaterfallFlow.extent(
|
: SliverPadding(
|
||||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
padding: EdgeInsets.only(
|
||||||
children: [
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
..._list.map((item) => item.widget),
|
|
||||||
SizedBox(
|
|
||||||
height: MediaQuery.paddingOf(context).bottom + 80,
|
|
||||||
),
|
),
|
||||||
],
|
sliver: SliverWaterfallFlow.extent(
|
||||||
),
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||||
],
|
children: [
|
||||||
),
|
..._list.map((item) => item.widget),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,24 +121,35 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
: Row(
|
: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(flex: 40, child: _buildList),
|
Expanded(
|
||||||
|
flex: 4,
|
||||||
|
child: MediaQuery.removePadding(
|
||||||
|
context: context,
|
||||||
|
removeRight: true,
|
||||||
|
child: _buildList,
|
||||||
|
),
|
||||||
|
),
|
||||||
VerticalDivider(
|
VerticalDivider(
|
||||||
width: 1,
|
width: 1,
|
||||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 60,
|
flex: 6,
|
||||||
child: switch (_type) {
|
child: MediaQuery.removePadding(
|
||||||
'privacySetting' => PrivacySetting(showAppBar: false),
|
context: context,
|
||||||
'recommendSetting' => RecommendSetting(showAppBar: false),
|
removeLeft: true,
|
||||||
'videoSetting' => VideoSetting(showAppBar: false),
|
child: switch (_type) {
|
||||||
'playSetting' => PlaySetting(showAppBar: false),
|
'privacySetting' => PrivacySetting(showAppBar: false),
|
||||||
'styleSetting' => StyleSetting(showAppBar: false),
|
'recommendSetting' => RecommendSetting(showAppBar: false),
|
||||||
'extraSetting' => ExtraSetting(showAppBar: false),
|
'videoSetting' => VideoSetting(showAppBar: false),
|
||||||
'webdavSetting' => WebDavSettingPage(showAppBar: false),
|
'playSetting' => PlaySetting(showAppBar: false),
|
||||||
'about' => AboutPage(showAppBar: false),
|
'styleSetting' => StyleSetting(showAppBar: false),
|
||||||
_ => const SizedBox.shrink(),
|
'extraSetting' => ExtraSetting(showAppBar: false),
|
||||||
},
|
'webdavSetting' => WebDavSettingPage(showAppBar: false),
|
||||||
|
'about' => AboutPage(showAppBar: false),
|
||||||
|
_ => const SizedBox.shrink(),
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -23,19 +23,23 @@ class _SubPageState extends State<SubPage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('我的订阅')),
|
appBar: AppBar(title: const Text('我的订阅')),
|
||||||
body: refreshIndicator(
|
body: SafeArea(
|
||||||
onRefresh: () async {
|
top: false,
|
||||||
await _subController.onRefresh();
|
bottom: false,
|
||||||
},
|
child: refreshIndicator(
|
||||||
child: CustomScrollView(
|
onRefresh: () async {
|
||||||
slivers: [
|
await _subController.onRefresh();
|
||||||
Obx(() => _buildBody(_subController.loadingState.value)),
|
},
|
||||||
SliverToBoxAdapter(
|
child: CustomScrollView(
|
||||||
child: SizedBox(
|
slivers: [
|
||||||
height: MediaQuery.of(context).padding.bottom + 80,
|
Obx(() => _buildBody(_subController.loadingState.value)),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: SizedBox(
|
||||||
|
height: MediaQuery.of(context).padding.bottom + 80,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
|||||||
|
|
||||||
Widget get _buildCount => SliverToBoxAdapter(
|
Widget get _buildCount => SliverToBoxAdapter(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14),
|
padding: const EdgeInsets.only(top: 12, bottom: 8, left: 14),
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Text(
|
() => Text(
|
||||||
'共${_subDetailController.mediaCount}条视频',
|
'共${_subDetailController.mediaCount}条视频',
|
||||||
@@ -118,7 +118,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Widget get _buildAppBar => SliverAppBar(
|
Widget get _buildAppBar => SliverAppBar(
|
||||||
expandedHeight: 215 - MediaQuery.paddingOf(context).bottom,
|
expandedHeight: 210 - MediaQuery.paddingOf(context).top,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
title: Obx(
|
title: Obx(
|
||||||
() {
|
() {
|
||||||
@@ -158,7 +158,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
|||||||
top: kTextTabBarHeight + MediaQuery.of(context).padding.top + 15,
|
top: kTextTabBarHeight + MediaQuery.of(context).padding.top + 15,
|
||||||
left: 12,
|
left: 12,
|
||||||
right: 12,
|
right: 12,
|
||||||
bottom: 20,
|
bottom: 12,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@@ -31,11 +31,7 @@ class _WhisperPageState extends State<WhisperPage> {
|
|||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverSafeArea(
|
_buildTopItems,
|
||||||
top: false,
|
|
||||||
bottom: false,
|
|
||||||
sliver: _buildTopItems,
|
|
||||||
),
|
|
||||||
Obx(() => _buildBody(_whisperController.loadingState.value)),
|
Obx(() => _buildBody(_whisperController.loadingState.value)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -90,59 +86,63 @@ class _WhisperPageState extends State<WhisperPage> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget get _buildTopItems => SliverToBoxAdapter(
|
Widget get _buildTopItems => SliverSafeArea(
|
||||||
child: Row(
|
top: false,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
bottom: false,
|
||||||
children:
|
sliver: SliverToBoxAdapter(
|
||||||
List.generate(_whisperController.msgFeedTopItems.length, (index) {
|
child: Row(
|
||||||
return GestureDetector(
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
behavior: HitTestBehavior.opaque,
|
children: List.generate(_whisperController.msgFeedTopItems.length,
|
||||||
child: Padding(
|
(index) {
|
||||||
padding: const EdgeInsets.all(10),
|
return GestureDetector(
|
||||||
child: Column(
|
behavior: HitTestBehavior.opaque,
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Padding(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
padding: const EdgeInsets.all(10),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Column(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
Obx(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
() => Badge(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
isLabelVisible:
|
children: [
|
||||||
_whisperController.unreadCounts[index] > 0,
|
Obx(
|
||||||
label:
|
() => Badge(
|
||||||
Text(" ${_whisperController.unreadCounts[index]} "),
|
isLabelVisible:
|
||||||
alignment: Alignment.topRight,
|
_whisperController.unreadCounts[index] > 0,
|
||||||
child: CircleAvatar(
|
label: Text(
|
||||||
radius: 22,
|
" ${_whisperController.unreadCounts[index]} "),
|
||||||
backgroundColor:
|
alignment: Alignment.topRight,
|
||||||
Theme.of(context).colorScheme.onInverseSurface,
|
child: CircleAvatar(
|
||||||
child: Icon(
|
radius: 22,
|
||||||
_whisperController.msgFeedTopItems[index]['icon'],
|
backgroundColor:
|
||||||
size: 20,
|
Theme.of(context).colorScheme.onInverseSurface,
|
||||||
color: Theme.of(context).colorScheme.primary,
|
child: Icon(
|
||||||
|
_whisperController.msgFeedTopItems[index]['icon'],
|
||||||
|
size: 20,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 6),
|
||||||
const SizedBox(height: 6),
|
Text(
|
||||||
Text(
|
_whisperController.msgFeedTopItems[index]['name'],
|
||||||
_whisperController.msgFeedTopItems[index]['name'],
|
style: const TextStyle(fontSize: 13),
|
||||||
style: const TextStyle(fontSize: 13),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
onTap: () {
|
||||||
onTap: () {
|
if (!_whisperController.msgFeedTopItems[index]['enabled']) {
|
||||||
if (!_whisperController.msgFeedTopItems[index]['enabled']) {
|
SmartDialog.showToast('已禁用');
|
||||||
SmartDialog.showToast('已禁用');
|
return;
|
||||||
return;
|
}
|
||||||
}
|
_whisperController.unreadCounts[index] = 0;
|
||||||
_whisperController.unreadCounts[index] = 0;
|
Get.toNamed(
|
||||||
Get.toNamed(
|
_whisperController.msgFeedTopItems[index]['route'],
|
||||||
_whisperController.msgFeedTopItems[index]['route'],
|
);
|
||||||
);
|
},
|
||||||
},
|
);
|
||||||
);
|
}).toList(),
|
||||||
}).toList(),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,21 +94,25 @@ class _WhisperDetailPageState
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: Column(
|
body: SafeArea(
|
||||||
children: [
|
top: false,
|
||||||
Expanded(
|
bottom: false,
|
||||||
child: Listener(
|
child: Column(
|
||||||
child: Obx(() =>
|
children: [
|
||||||
_buildBody(_whisperDetailController.loadingState.value)),
|
Expanded(
|
||||||
onPointerDown: (event) {
|
child: Listener(
|
||||||
// Hide panel when touch ListView.
|
child: Obx(() =>
|
||||||
hidePanel();
|
_buildBody(_whisperDetailController.loadingState.value)),
|
||||||
},
|
onPointerDown: (event) {
|
||||||
|
// Hide panel when touch ListView.
|
||||||
|
hidePanel();
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
_buildInputView(),
|
||||||
_buildInputView(),
|
buildPanelContainer(Theme.of(context).colorScheme.onInverseSurface),
|
||||||
buildPanelContainer(Theme.of(context).colorScheme.onInverseSurface),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user