Merge branch 'design'

This commit is contained in:
guozhigq
2024-06-20 23:54:35 +08:00
9 changed files with 105 additions and 55 deletions

View File

@ -2,12 +2,18 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
class HttpError extends StatelessWidget { class HttpError extends StatelessWidget {
const HttpError( const HttpError({
{required this.errMsg, required this.fn, this.btnText, super.key}); required this.errMsg,
required this.fn,
this.btnText,
this.isShowBtn = true,
super.key,
});
final String? errMsg; final String? errMsg;
final Function()? fn; final Function()? fn;
final String? btnText; final String? btnText;
final bool isShowBtn;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -29,20 +35,22 @@ class HttpError extends StatelessWidget {
style: Theme.of(context).textTheme.titleSmall, style: Theme.of(context).textTheme.titleSmall,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
FilledButton.tonal( if (isShowBtn)
onPressed: () { FilledButton.tonal(
fn!(); onPressed: () {
}, fn!();
style: ButtonStyle( },
backgroundColor: MaterialStateProperty.resolveWith((states) { style: ButtonStyle(
return Theme.of(context).colorScheme.primary.withAlpha(20); backgroundColor: MaterialStateProperty.resolveWith((states) {
}), return Theme.of(context).colorScheme.primary.withAlpha(20);
}),
),
child: Text(
btnText ?? '点击重试',
style:
TextStyle(color: Theme.of(context).colorScheme.primary),
),
), ),
child: Text(
btnText ?? '点击重试',
style: TextStyle(color: Theme.of(context).colorScheme.primary),
),
),
], ],
), ),
), ),

View File

@ -88,7 +88,11 @@ class SearchHttp {
if (tids != null && tids != -1) 'tids': tids, if (tids != null && tids != -1) 'tids': tids,
}; };
var res = await Request().get(Api.searchByType, data: reqData); var res = await Request().get(Api.searchByType, data: reqData);
if (res.data['code'] == 0 && res.data['data']['numPages'] > 0) { if (res.data['code'] == 0) {
if (res.data['data']['numPages'] == 0) {
// 我想返回数据使得可以通过data.list 取值,结果为[]
return {'status': true, 'data': Data()};
}
Object data; Object data;
try { try {
switch (searchType) { switch (searchType) {
@ -125,9 +129,7 @@ class SearchHttp {
return { return {
'status': false, 'status': false,
'data': [], 'data': [],
'msg': res.data['data'] != null && res.data['data']['numPages'] == 0 'msg': res.data['message'],
? '没有相关数据'
: res.data['message'],
}; };
} }
} }
@ -206,3 +208,9 @@ class SearchHttp {
} }
} }
} }
class Data {
List<dynamic> list;
Data({this.list = const []});
}

View File

@ -5,10 +5,12 @@ class SearchVideoModel {
SearchVideoModel({this.list}); SearchVideoModel({this.list});
List<SearchVideoItemModel>? list; List<SearchVideoItemModel>? list;
SearchVideoModel.fromJson(Map<String, dynamic> json) { SearchVideoModel.fromJson(Map<String, dynamic> json) {
list = json['result'] list = json['result'] == null
.where((e) => e['available'] == true) ? []
.map<SearchVideoItemModel>((e) => SearchVideoItemModel.fromJson(e)) : json['result']
.toList(); .where((e) => e['available'] == true)
.map<SearchVideoItemModel>((e) => SearchVideoItemModel.fromJson(e))
.toList();
} }
} }

View File

@ -357,25 +357,29 @@ class CustomChip extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ColorScheme colorTheme = Theme.of(context).colorScheme; final ColorScheme colorTheme = Theme.of(context).colorScheme;
final Color secondaryContainer = colorTheme.secondaryContainer; final Color secondaryContainer = colorTheme.secondaryContainer;
final Color onPrimary = colorTheme.onPrimary;
final Color primary = colorTheme.primary;
final TextStyle chipTextStyle = selected final TextStyle chipTextStyle = selected
? const TextStyle(fontWeight: FontWeight.bold, fontSize: 13) ? TextStyle(fontSize: 13, color: onPrimary)
: const TextStyle(fontSize: 13); : TextStyle(fontSize: 13, color: colorTheme.onSecondaryContainer);
final ColorScheme colorScheme = Theme.of(context).colorScheme;
const VisualDensity visualDensity = const VisualDensity visualDensity =
VisualDensity(horizontal: -4.0, vertical: -2.0); VisualDensity(horizontal: -4.0, vertical: -2.0);
return InputChip( return InputChip(
side: BorderSide( side: BorderSide.none,
color: selected
? colorScheme.onSecondaryContainer.withOpacity(0.2)
: Colors.transparent,
),
backgroundColor: secondaryContainer, backgroundColor: secondaryContainer,
selectedColor: secondaryContainer, color: MaterialStateProperty.resolveWith((states) {
color: MaterialStateProperty.resolveWith<Color>( if (states.contains(MaterialState.selected) ||
(Set<MaterialState> states) => secondaryContainer.withAlpha(200)), states.contains(MaterialState.hovered)) {
padding: const EdgeInsets.fromLTRB(7, 1, 7, 1), return primary;
}
return colorTheme.secondaryContainer;
}),
padding: const EdgeInsets.fromLTRB(6, 1, 6, 1),
label: Text(label, style: chipTextStyle), label: Text(label, style: chipTextStyle),
onPressed: () => onTap(), onPressed: () => onTap(),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
selected: selected, selected: selected,
showCheckmark: false, showCheckmark: false,
visualDensity: visualDensity, visualDensity: visualDensity,

View File

@ -30,9 +30,9 @@ class SearchPanelController extends GetxController {
); );
if (result['status']) { if (result['status']) {
if (type == 'onRefresh') { if (type == 'onRefresh') {
resultList.value = result['data'].list; resultList.value = result['data'].list ?? [];
} else { } else {
resultList.addAll(result['data'].list); resultList.addAll(result['data'].list ?? []);
} }
page.value++; page.value++;
onPushDetail(keyword, resultList); onPushDetail(keyword, resultList);

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/common/widgets/video_card_h.dart'; import 'package:pilipala/common/widgets/video_card_h.dart';
import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/models/common/search_type.dart';
import 'package:pilipala/pages/search/widgets/search_text.dart'; import 'package:pilipala/pages/search/widgets/search_text.dart';
@ -25,25 +26,35 @@ class SearchVideoPanel extends StatelessWidget {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.only(top: 36), padding: const EdgeInsets.only(top: 36),
child: ListView.builder( child: list!.isNotEmpty
controller: ctr!.scrollController, ? ListView.builder(
addAutomaticKeepAlives: false, controller: ctr!.scrollController,
addRepaintBoundaries: false, addAutomaticKeepAlives: false,
itemCount: list!.length, addRepaintBoundaries: false,
itemBuilder: (context, index) { itemCount: list!.length,
var i = list![index]; itemBuilder: (context, index) {
return Padding( var i = list![index];
padding: index == 0 return Padding(
? const EdgeInsets.only(top: 2) padding: index == 0
: EdgeInsets.zero, ? const EdgeInsets.only(top: 2)
child: VideoCardH( : EdgeInsets.zero,
videoItem: i, child: VideoCardH(
showPubdate: true, videoItem: i,
source: 'search', showPubdate: true,
source: 'search',
),
);
},
)
: CustomScrollView(
slivers: [
HttpError(
errMsg: '没有数据',
isShowBtn: false,
fn: () => {},
)
],
), ),
);
},
),
), ),
// 分类筛选 // 分类筛选
Container( Container(

View File

@ -109,6 +109,7 @@ class VideoDetailController extends GetxController
].obs; ].obs;
RxDouble sheetHeight = 0.0.obs; RxDouble sheetHeight = 0.0.obs;
RxString archiveSourceType = 'dash'.obs; RxString archiveSourceType = 'dash'.obs;
ScrollController? replyScrillController;
@override @override
void onInit() { void onInit() {
@ -551,4 +552,15 @@ class VideoDetailController extends GetxController
cover.value = videoItem['pic'] = pic; cover.value = videoItem['pic'] = pic;
} }
} }
void onControllerCreated(ScrollController controller) {
replyScrillController = controller;
}
void onTapTabbar(int index) {
if (index == 1 && tabCtr.index == 1) {
replyScrillController?.animateTo(0,
duration: const Duration(milliseconds: 300), curve: Curves.ease);
}
}
} }

View File

@ -19,12 +19,14 @@ class VideoReplyPanel extends StatefulWidget {
final int? oid; final int? oid;
final int rpid; final int rpid;
final String? replyLevel; final String? replyLevel;
final Function(ScrollController)? onControllerCreated;
const VideoReplyPanel({ const VideoReplyPanel({
this.bvid, this.bvid,
this.oid, this.oid,
this.rpid = 0, this.rpid = 0,
this.replyLevel, this.replyLevel,
this.onControllerCreated,
super.key, super.key,
}); });
@ -68,6 +70,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
_futureBuilderFuture = _videoReplyController.queryReplyList(); _futureBuilderFuture = _videoReplyController.queryReplyList();
scrollController = ScrollController(); scrollController = ScrollController();
widget.onControllerCreated?.call(scrollController);
fabAnimationCtr.forward(); fabAnimationCtr.forward();
scrollListener(); scrollListener();
} }

View File

@ -387,6 +387,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
dividerColor: Colors.transparent, dividerColor: Colors.transparent,
tabs: tabs:
vdCtr.tabs.map((String name) => Tab(text: name)).toList(), vdCtr.tabs.map((String name) => Tab(text: name)).toList(),
onTap: (index) => vdCtr.onTapTabbar(index),
), ),
), ),
), ),
@ -683,6 +684,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
() => VideoReplyPanel( () => VideoReplyPanel(
bvid: vdCtr.bvid, bvid: vdCtr.bvid,
oid: vdCtr.oid.value, oid: vdCtr.oid.value,
onControllerCreated: vdCtr.onControllerCreated,
), ),
) )
], ],