feat: 动态主楼评论
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/http/reply.dart';
|
import 'package:pilipala/http/reply.dart';
|
||||||
@ -17,6 +18,7 @@ class DynamicDetailController extends GetxController {
|
|||||||
RxString noMore = ''.obs;
|
RxString noMore = ''.obs;
|
||||||
RxList<ReplyItemModel> replyList = [ReplyItemModel()].obs;
|
RxList<ReplyItemModel> replyList = [ReplyItemModel()].obs;
|
||||||
RxInt acount = 0.obs;
|
RxInt acount = 0.obs;
|
||||||
|
final ScrollController scrollController = ScrollController();
|
||||||
|
|
||||||
ReplySortType _sortType = ReplySortType.time;
|
ReplySortType _sortType = ReplySortType.time;
|
||||||
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:easy_debounce/easy_throttle.dart';
|
import 'package:easy_debounce/easy_throttle.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/skeleton/video_reply.dart';
|
import 'package:pilipala/common/skeleton/video_reply.dart';
|
||||||
import 'package:pilipala/common/widgets/http_error.dart';
|
import 'package:pilipala/common/widgets/http_error.dart';
|
||||||
@ -9,7 +10,10 @@ import 'package:pilipala/models/common/reply_type.dart';
|
|||||||
import 'package:pilipala/pages/dynamics/deatil/index.dart';
|
import 'package:pilipala/pages/dynamics/deatil/index.dart';
|
||||||
import 'package:pilipala/pages/dynamics/widgets/author_panel.dart';
|
import 'package:pilipala/pages/dynamics/widgets/author_panel.dart';
|
||||||
import 'package:pilipala/pages/video/detail/reply/widgets/reply_item.dart';
|
import 'package:pilipala/pages/video/detail/reply/widgets/reply_item.dart';
|
||||||
|
import 'package:pilipala/pages/video/detail/replyNew/index.dart';
|
||||||
import 'package:pilipala/pages/video/detail/replyReply/index.dart';
|
import 'package:pilipala/pages/video/detail/replyReply/index.dart';
|
||||||
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
|
import 'package:pilipala/utils/id_utils.dart';
|
||||||
|
|
||||||
import '../widgets/dynamic_panel.dart';
|
import '../widgets/dynamic_panel.dart';
|
||||||
|
|
||||||
@ -21,15 +25,18 @@ class DynamicDetailPage extends StatefulWidget {
|
|||||||
State<DynamicDetailPage> createState() => _DynamicDetailPageState();
|
State<DynamicDetailPage> createState() => _DynamicDetailPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DynamicDetailPageState extends State<DynamicDetailPage> {
|
class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||||
late DynamicDetailController? _dynamicDetailController;
|
with TickerProviderStateMixin {
|
||||||
|
late DynamicDetailController _dynamicDetailController;
|
||||||
|
late AnimationController fabAnimationCtr;
|
||||||
Future? _futureBuilderFuture;
|
Future? _futureBuilderFuture;
|
||||||
late StreamController<bool> titleStreamC; // appBar title
|
late StreamController<bool> titleStreamC; // appBar title
|
||||||
final ScrollController scrollController = ScrollController();
|
late ScrollController scrollController;
|
||||||
bool _visibleTitle = false;
|
bool _visibleTitle = false;
|
||||||
String? action;
|
String? action;
|
||||||
// 回复类型
|
// 回复类型
|
||||||
late int type;
|
late int type;
|
||||||
|
bool _isFabVisible = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -50,37 +57,30 @@ class _DynamicDetailPageState extends State<DynamicDetailPage> {
|
|||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
int commentType = Get.arguments['item'].basic!['comment_type'] ?? 11;
|
int commentType = 11;
|
||||||
|
try {
|
||||||
|
commentType = Get.arguments['item'].basic!['comment_type'];
|
||||||
|
} catch (_) {}
|
||||||
type = (commentType == 0) ? 11 : commentType;
|
type = (commentType == 0) ? 11 : commentType;
|
||||||
|
|
||||||
action =
|
action =
|
||||||
Get.arguments.containsKey('action') ? Get.arguments['action'] : null;
|
Get.arguments.containsKey('action') ? Get.arguments['action'] : null;
|
||||||
_dynamicDetailController =
|
_dynamicDetailController =
|
||||||
Get.put(DynamicDetailController(oid, type), tag: oid.toString());
|
Get.put(DynamicDetailController(oid, type), tag: oid.toString());
|
||||||
_futureBuilderFuture = _dynamicDetailController!.queryReplyList();
|
_futureBuilderFuture = _dynamicDetailController.queryReplyList();
|
||||||
titleStreamC = StreamController<bool>();
|
titleStreamC = StreamController<bool>();
|
||||||
scrollController.addListener(_listen);
|
|
||||||
if (action == 'comment') {
|
if (action == 'comment') {
|
||||||
_visibleTitle = true;
|
_visibleTitle = true;
|
||||||
titleStreamC.add(true);
|
titleStreamC.add(true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _listen() async {
|
fabAnimationCtr = AnimationController(
|
||||||
if (scrollController.position.pixels >=
|
vsync: this,
|
||||||
scrollController.position.maxScrollExtent - 300) {
|
duration: const Duration(milliseconds: 300),
|
||||||
EasyThrottle.throttle('replylist', const Duration(seconds: 2), () {
|
);
|
||||||
_dynamicDetailController!.queryReplyList(reqType: 'onLoad');
|
fabAnimationCtr.forward();
|
||||||
});
|
// 滚动事件监听
|
||||||
}
|
scrollListener();
|
||||||
|
|
||||||
if (scrollController.offset > 55 && !_visibleTitle) {
|
|
||||||
_visibleTitle = true;
|
|
||||||
titleStreamC.add(true);
|
|
||||||
} else if (scrollController.offset <= 55 && _visibleTitle) {
|
|
||||||
_visibleTitle = false;
|
|
||||||
titleStreamC.add(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void replyReply(replyItem) {
|
void replyReply(replyItem) {
|
||||||
@ -107,9 +107,58 @@ class _DynamicDetailPageState extends State<DynamicDetailPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scrollListener() {
|
||||||
|
scrollController = _dynamicDetailController.scrollController;
|
||||||
|
scrollController.addListener(
|
||||||
|
() {
|
||||||
|
// 分页加载
|
||||||
|
if (scrollController.position.pixels >=
|
||||||
|
scrollController.position.maxScrollExtent - 300) {
|
||||||
|
EasyThrottle.throttle('replylist', const Duration(seconds: 2), () {
|
||||||
|
_dynamicDetailController.queryReplyList(reqType: 'onLoad');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标题
|
||||||
|
if (scrollController.offset > 55 && !_visibleTitle) {
|
||||||
|
_visibleTitle = true;
|
||||||
|
titleStreamC.add(true);
|
||||||
|
} else if (scrollController.offset <= 55 && _visibleTitle) {
|
||||||
|
_visibleTitle = false;
|
||||||
|
titleStreamC.add(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fab按钮
|
||||||
|
final ScrollDirection direction =
|
||||||
|
scrollController.position.userScrollDirection;
|
||||||
|
if (direction == ScrollDirection.forward) {
|
||||||
|
_showFab();
|
||||||
|
} else if (direction == ScrollDirection.reverse) {
|
||||||
|
_hideFab();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showFab() {
|
||||||
|
if (!_isFabVisible) {
|
||||||
|
_isFabVisible = true;
|
||||||
|
fabAnimationCtr.forward();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _hideFab() {
|
||||||
|
if (_isFabVisible) {
|
||||||
|
_isFabVisible = false;
|
||||||
|
fabAnimationCtr.reverse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
scrollController.removeListener(() {});
|
scrollController.removeListener(() {});
|
||||||
|
fabAnimationCtr.dispose();
|
||||||
|
scrollController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,155 +185,206 @@ class _DynamicDetailPageState extends State<DynamicDetailPage> {
|
|||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
await _dynamicDetailController!.queryReplyList();
|
await _dynamicDetailController.queryReplyList();
|
||||||
},
|
},
|
||||||
child: CustomScrollView(
|
child: Stack(
|
||||||
controller: scrollController,
|
children: [
|
||||||
slivers: [
|
CustomScrollView(
|
||||||
if (action != 'comment')
|
controller: scrollController,
|
||||||
SliverToBoxAdapter(
|
slivers: [
|
||||||
child: DynamicPanel(
|
if (action != 'comment')
|
||||||
item: _dynamicDetailController!.item,
|
SliverToBoxAdapter(
|
||||||
source: 'detail',
|
child: DynamicPanel(
|
||||||
),
|
item: _dynamicDetailController.item,
|
||||||
),
|
source: 'detail',
|
||||||
SliverPersistentHeader(
|
|
||||||
delegate: _MySliverPersistentHeaderDelegate(
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
border: Border(
|
|
||||||
top: BorderSide(
|
|
||||||
width: 0.6,
|
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.05),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
height: 45,
|
SliverPersistentHeader(
|
||||||
padding: const EdgeInsets.only(left: 12, right: 6),
|
delegate: _MySliverPersistentHeaderDelegate(
|
||||||
child: Row(
|
child: Container(
|
||||||
children: [
|
decoration: BoxDecoration(
|
||||||
Obx(
|
color: Theme.of(context).colorScheme.surface,
|
||||||
() => AnimatedSwitcher(
|
border: Border(
|
||||||
duration: const Duration(milliseconds: 400),
|
top: BorderSide(
|
||||||
transitionBuilder:
|
width: 0.6,
|
||||||
(Widget child, Animation<double> animation) {
|
color: Theme.of(context)
|
||||||
return ScaleTransition(
|
.dividerColor
|
||||||
scale: animation, child: child);
|
.withOpacity(0.05),
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'${_dynamicDetailController!.acount.value}',
|
|
||||||
key: ValueKey<int>(
|
|
||||||
_dynamicDetailController!.acount.value),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Text('条回复'),
|
height: 45,
|
||||||
const Spacer(),
|
padding: const EdgeInsets.only(left: 12, right: 6),
|
||||||
SizedBox(
|
child: Row(
|
||||||
height: 35,
|
children: [
|
||||||
child: TextButton.icon(
|
Obx(
|
||||||
onPressed: () =>
|
() => AnimatedSwitcher(
|
||||||
_dynamicDetailController!.queryBySort(),
|
duration: const Duration(milliseconds: 400),
|
||||||
icon: const Icon(Icons.sort, size: 16),
|
transitionBuilder:
|
||||||
label: Obx(() => Text(
|
(Widget child, Animation<double> animation) {
|
||||||
_dynamicDetailController!.sortTypeLabel.value,
|
return ScaleTransition(
|
||||||
style: const TextStyle(fontSize: 13),
|
scale: animation, child: child);
|
||||||
)),
|
},
|
||||||
),
|
child: Text(
|
||||||
)
|
'${_dynamicDetailController.acount.value}',
|
||||||
],
|
key: ValueKey<int>(
|
||||||
),
|
_dynamicDetailController.acount.value),
|
||||||
),
|
|
||||||
),
|
|
||||||
pinned: true,
|
|
||||||
),
|
|
||||||
FutureBuilder(
|
|
||||||
future: _futureBuilderFuture,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
|
||||||
Map data = snapshot.data as Map;
|
|
||||||
if (snapshot.data['status']) {
|
|
||||||
// 请求成功
|
|
||||||
return Obx(
|
|
||||||
() => _dynamicDetailController!.replyList.isEmpty &&
|
|
||||||
_dynamicDetailController!.isLoadingMore
|
|
||||||
? SliverList(
|
|
||||||
delegate:
|
|
||||||
SliverChildBuilderDelegate((context, index) {
|
|
||||||
return const VideoReplySkeleton();
|
|
||||||
}, childCount: 8),
|
|
||||||
)
|
|
||||||
: SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
if (index ==
|
|
||||||
_dynamicDetailController!
|
|
||||||
.replyList.length) {
|
|
||||||
return Container(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
bottom: MediaQuery.of(context)
|
|
||||||
.padding
|
|
||||||
.bottom),
|
|
||||||
height: MediaQuery.of(context)
|
|
||||||
.padding
|
|
||||||
.bottom +
|
|
||||||
100,
|
|
||||||
child: Center(
|
|
||||||
child: Obx(
|
|
||||||
() => Text(
|
|
||||||
_dynamicDetailController!
|
|
||||||
.noMore.value,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return ReplyItem(
|
|
||||||
replyItem: _dynamicDetailController!
|
|
||||||
.replyList[index],
|
|
||||||
showReplyRow: true,
|
|
||||||
replyLevel: '1',
|
|
||||||
replyReply: (replyItem) =>
|
|
||||||
replyReply(replyItem),
|
|
||||||
replyType: ReplyType.values[type],
|
|
||||||
addReply: (replyItem) {
|
|
||||||
_dynamicDetailController!
|
|
||||||
.replyList[index].replies!
|
|
||||||
.add(replyItem);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
childCount:
|
|
||||||
_dynamicDetailController!.replyList.length +
|
|
||||||
1,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
const Text('条回复'),
|
||||||
|
const Spacer(),
|
||||||
|
SizedBox(
|
||||||
|
height: 35,
|
||||||
|
child: TextButton.icon(
|
||||||
|
onPressed: () =>
|
||||||
|
_dynamicDetailController.queryBySort(),
|
||||||
|
icon: const Icon(Icons.sort, size: 16),
|
||||||
|
label: Obx(() => Text(
|
||||||
|
_dynamicDetailController
|
||||||
|
.sortTypeLabel.value,
|
||||||
|
style: const TextStyle(fontSize: 13),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pinned: true,
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: _futureBuilderFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
|
Map data = snapshot.data as Map;
|
||||||
|
if (snapshot.data['status']) {
|
||||||
|
// 请求成功
|
||||||
|
return Obx(
|
||||||
|
() => _dynamicDetailController.replyList.isEmpty &&
|
||||||
|
_dynamicDetailController.isLoadingMore
|
||||||
|
? SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(context, index) {
|
||||||
|
return const VideoReplySkeleton();
|
||||||
|
}, childCount: 8),
|
||||||
|
)
|
||||||
|
: SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(context, index) {
|
||||||
|
if (index ==
|
||||||
|
_dynamicDetailController
|
||||||
|
.replyList.length) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.of(context)
|
||||||
|
.padding
|
||||||
|
.bottom),
|
||||||
|
height: MediaQuery.of(context)
|
||||||
|
.padding
|
||||||
|
.bottom +
|
||||||
|
100,
|
||||||
|
child: Center(
|
||||||
|
child: Obx(
|
||||||
|
() => Text(
|
||||||
|
_dynamicDetailController
|
||||||
|
.noMore.value,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return ReplyItem(
|
||||||
|
replyItem: _dynamicDetailController
|
||||||
|
.replyList[index],
|
||||||
|
showReplyRow: true,
|
||||||
|
replyLevel: '1',
|
||||||
|
replyReply: (replyItem) =>
|
||||||
|
replyReply(replyItem),
|
||||||
|
replyType: ReplyType.values[type],
|
||||||
|
addReply: (replyItem) {
|
||||||
|
_dynamicDetailController
|
||||||
|
.replyList[index].replies!
|
||||||
|
.add(replyItem);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
childCount: _dynamicDetailController
|
||||||
|
.replyList.length +
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 请求错误
|
||||||
|
return HttpError(
|
||||||
|
errMsg: data['msg'],
|
||||||
|
fn: () => setState(() {}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 骨架屏
|
||||||
|
return SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
|
return const VideoReplySkeleton();
|
||||||
|
}, childCount: 8),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 14,
|
||||||
|
right: 14,
|
||||||
|
child: SlideTransition(
|
||||||
|
position: Tween<Offset>(
|
||||||
|
begin: const Offset(0, 2),
|
||||||
|
end: const Offset(0, 0),
|
||||||
|
).animate(CurvedAnimation(
|
||||||
|
parent: fabAnimationCtr,
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
)),
|
||||||
|
child: FloatingActionButton(
|
||||||
|
heroTag: null,
|
||||||
|
onPressed: () {
|
||||||
|
feedBack();
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return VideoReplyNewDialog(
|
||||||
|
oid: _dynamicDetailController.oid ??
|
||||||
|
IdUtils.bv2av(Get.parameters['bvid']!),
|
||||||
|
root: 0,
|
||||||
|
parent: 0,
|
||||||
|
replyType: ReplyType.values[type],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).then(
|
||||||
|
(value) => {
|
||||||
|
// 完成评论,数据添加
|
||||||
|
if (value != null && value['data'] != null)
|
||||||
|
{
|
||||||
|
_dynamicDetailController.replyList
|
||||||
|
.add(value['data']),
|
||||||
|
_dynamicDetailController.acount.value++
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
} else {
|
},
|
||||||
// 请求错误
|
tooltip: '评论动态',
|
||||||
return HttpError(
|
child: const Icon(Icons.reply),
|
||||||
errMsg: data['msg'],
|
),
|
||||||
fn: () => setState(() {}),
|
),
|
||||||
);
|
),
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 骨架屏
|
|
||||||
return SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate((context, index) {
|
|
||||||
return const VideoReplySkeleton();
|
|
||||||
}, childCount: 8),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -62,6 +62,12 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
vsync: this, duration: const Duration(milliseconds: 300));
|
vsync: this, duration: const Duration(milliseconds: 300));
|
||||||
|
|
||||||
_futureBuilderFuture = _videoReplyController.queryReplyList();
|
_futureBuilderFuture = _videoReplyController.queryReplyList();
|
||||||
|
|
||||||
|
fabAnimationCtr.forward();
|
||||||
|
scrollListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
void scrollListener() {
|
||||||
scrollController = _videoReplyController.scrollController;
|
scrollController = _videoReplyController.scrollController;
|
||||||
scrollController.addListener(
|
scrollController.addListener(
|
||||||
() {
|
() {
|
||||||
@ -81,7 +87,6 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
fabAnimationCtr.forward();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showFab() {
|
void _showFab() {
|
||||||
@ -112,9 +117,10 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
scrollController.removeListener(() {});
|
||||||
fabAnimationCtr.dispose();
|
fabAnimationCtr.dispose();
|
||||||
scrollController.dispose();
|
scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -128,7 +134,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
CustomScrollView(
|
CustomScrollView(
|
||||||
controller: _videoReplyController.scrollController,
|
controller: scrollController,
|
||||||
key: const PageStorageKey<String>('评论'),
|
key: const PageStorageKey<String>('评论'),
|
||||||
slivers: <Widget>[
|
slivers: <Widget>[
|
||||||
SliverPersistentHeader(
|
SliverPersistentHeader(
|
||||||
|
@ -744,11 +744,14 @@ InlineSpan buildContent(
|
|||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
// 跳转到指定位置
|
// 跳转到指定位置
|
||||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag'])
|
try {
|
||||||
.plPlayerController
|
Get.find<VideoDetailController>(
|
||||||
.seekTo(
|
tag: Get.arguments['heroTag'])
|
||||||
Duration(seconds: Utils.duration(matchStr)),
|
.plPlayerController
|
||||||
);
|
.seekTo(
|
||||||
|
Duration(seconds: Utils.duration(matchStr)),
|
||||||
|
);
|
||||||
|
} catch (_) {}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user