Merge branch 'home-design' into alpha

This commit is contained in:
guozhigq
2023-08-14 10:15:34 +08:00
18 changed files with 494 additions and 402 deletions

View File

@ -14,7 +14,7 @@ class VideoCardHSkeleton extends StatelessWidget {
child: LayoutBuilder( child: LayoutBuilder(
builder: (context, boxConstraints) { builder: (context, boxConstraints) {
double width = double width =
(boxConstraints.maxWidth - StyleString.cardSpace * 9) / 2; (boxConstraints.maxWidth - StyleString.cardSpace * 6) / 2;
return SizedBox( return SizedBox(
height: width / StyleString.aspectRatio, height: width / StyleString.aspectRatio,
child: Row( child: Row(

View File

@ -57,7 +57,7 @@ class VideoCardH extends StatelessWidget {
child: LayoutBuilder( child: LayoutBuilder(
builder: (context, boxConstraints) { builder: (context, boxConstraints) {
double width = double width =
(boxConstraints.maxWidth - StyleString.cardSpace * 9) / 2; (boxConstraints.maxWidth - StyleString.cardSpace * 6) / 2;
return SizedBox( return SizedBox(
height: width / StyleString.aspectRatio, height: width / StyleString.aspectRatio,
child: Row( child: Row(
@ -83,10 +83,10 @@ class VideoCardH extends StatelessWidget {
pBadge(Utils.timeFormat(videoItem.duration!), pBadge(Utils.timeFormat(videoItem.duration!),
context, null, 6.0, 6.0, null, context, null, 6.0, 6.0, null,
type: 'gray'), type: 'gray'),
if (videoItem.rcmdReason != null && // if (videoItem.rcmdReason != null &&
videoItem.rcmdReason.content != '') // videoItem.rcmdReason.content != '')
pBadge(videoItem.rcmdReason.content, context, // pBadge(videoItem.rcmdReason.content, context,
6.0, 6.0, null, null), // 6.0, 6.0, null, null),
], ],
); );
}, },
@ -124,7 +124,6 @@ class VideoContent extends StatelessWidget {
style: const TextStyle( style: const TextStyle(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
letterSpacing: 0.3,
), ),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -198,24 +197,59 @@ class VideoContent extends StatelessWidget {
// color: Theme.of(context).colorScheme.outline), // color: Theme.of(context).colorScheme.outline),
// ) // )
const Spacer(), const Spacer(),
// SizedBox(
// width: 20,
// height: 20,
// child: IconButton(
// tooltip: '稍后再看',
// style: ButtonStyle(
// padding: MaterialStateProperty.all(EdgeInsets.zero),
// ),
// onPressed: () async {
// var res =
// await UserHttp.toViewLater(bvid: videoItem.bvid);
// SmartDialog.showToast(res['msg']);
// },
// icon: Icon(
// Icons.more_vert_outlined,
// color: Theme.of(context).colorScheme.outline,
// size: 14,
// ),
// ),
// ),
SizedBox( SizedBox(
width: 20, width: 24,
height: 20, height: 24,
child: IconButton( child: PopupMenuButton<String>(
padding: EdgeInsets.zero,
tooltip: '稍后再看', tooltip: '稍后再看',
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero),
),
onPressed: () async {
var res =
await UserHttp.toViewLater(bvid: videoItem.bvid);
SmartDialog.showToast(res['msg']);
},
icon: Icon( icon: Icon(
Icons.more_vert_outlined, Icons.more_vert_outlined,
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
size: 14, size: 14,
), ),
position: PopupMenuPosition.under,
// constraints: const BoxConstraints(maxHeight: 35),
onSelected: (String type) {},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<String>>[
PopupMenuItem<String>(
onTap: () async {
var res =
await UserHttp.toViewLater(bvid: videoItem.bvid);
SmartDialog.showToast(res['msg']);
},
value: 'pause',
height: 35,
child: const Row(
children: [
Icon(Icons.watch_later_outlined, size: 16),
SizedBox(width: 6),
Text('稍后再看', style: TextStyle(fontSize: 13))
],
),
),
],
), ),
), ),
], ],

View File

@ -5,7 +5,6 @@ import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/stat/danmu.dart'; import 'package:pilipala/common/widgets/stat/danmu.dart';
import 'package:pilipala/common/widgets/stat/view.dart'; import 'package:pilipala/common/widgets/stat/view.dart';
import 'package:pilipala/http/user.dart'; import 'package:pilipala/http/user.dart';
import 'package:pilipala/pages/rcmd/index.dart';
import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/id_utils.dart';
import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/utils.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart';
@ -106,17 +105,13 @@ class VideoCardV extends StatelessWidget {
} }
class VideoContent extends StatelessWidget { class VideoContent extends StatelessWidget {
// ignore: prefer_typing_uninitialized_variables final dynamic videoItem;
final videoItem;
const VideoContent({Key? key, required this.videoItem}) : super(key: key); const VideoContent({Key? key, required this.videoItem}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Expanded( return Expanded(
child: Padding( child: Padding(
// 多列 padding: const EdgeInsets.fromLTRB(4, 8, 0, 3),
padding: const EdgeInsets.fromLTRB(4, 5, 0, 3),
// 单列
// padding: const EdgeInsets.fromLTRB(14, 10, 4, 8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -124,12 +119,8 @@ class VideoContent extends StatelessWidget {
Text( Text(
videoItem.title, videoItem.title,
textAlign: TextAlign.start, textAlign: TextAlign.start,
style: const TextStyle( style: const TextStyle(fontSize: 13),
fontSize: 13, maxLines: 2,
fontWeight: FontWeight.w500,
letterSpacing: 0.3,
),
maxLines: Get.find<RcmdController>().crossAxisCount,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -181,38 +172,90 @@ class VideoContent extends StatelessWidget {
}), }),
), ),
SizedBox( SizedBox(
width: 20, width: 24,
height: 20, height: 24,
child: IconButton( child: PopupMenuButton<String>(
padding: EdgeInsets.zero,
tooltip: '稍后再看', tooltip: '稍后再看',
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero),
),
onPressed: () async {
var res =
await UserHttp.toViewLater(bvid: videoItem.bvid);
SmartDialog.showToast(res['msg']);
},
icon: Icon( icon: Icon(
Icons.more_vert_outlined, Icons.more_vert_outlined,
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
size: 14, size: 14,
), ),
position: PopupMenuPosition.under,
// constraints: const BoxConstraints(maxHeight: 35),
onSelected: (String type) {},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<String>>[
PopupMenuItem<String>(
onTap: () async {
var res =
await UserHttp.toViewLater(bvid: videoItem.bvid);
SmartDialog.showToast(res['msg']);
},
value: 'pause',
height: 35,
child: const Row(
children: [
Icon(Icons.watch_later_outlined, size: 16),
SizedBox(width: 6),
Text('稍后再看', style: TextStyle(fontSize: 13))
],
),
),
],
), ),
), ),
], ],
), ),
// Row( // Row(
// children: [ // children: [
// const SizedBox(width: 1),
// StatView( // StatView(
// theme: 'black', // theme: 'gray',
// view: videoItem.stat.view, // view: videoItem.stat.view,
// ), // ),
// const SizedBox(width: 6), // const SizedBox(width: 10),
// StatDanMu( // StatDanMu(
// theme: 'black', // theme: 'gray',
// danmu: videoItem.stat.danmaku, // danmu: videoItem.stat.danmaku,
// ), // ),
// const Spacer(),
// SizedBox(
// width: 24,
// height: 24,
// child: PopupMenuButton<String>(
// padding: EdgeInsets.zero,
// tooltip: '稍后再看',
// icon: Icon(
// Icons.more_vert_outlined,
// color: Theme.of(context).colorScheme.outline,
// size: 14,
// ),
// position: PopupMenuPosition.under,
// // constraints: const BoxConstraints(maxHeight: 35),
// onSelected: (String type) {},
// itemBuilder: (BuildContext context) =>
// <PopupMenuEntry<String>>[
// PopupMenuItem<String>(
// onTap: () async {
// var res =
// await UserHttp.toViewLater(bvid: videoItem.bvid);
// SmartDialog.showToast(res['msg']);
// },
// value: 'pause',
// height: 35,
// child: const Row(
// children: [
// Icon(Icons.watch_later_outlined, size: 16),
// SizedBox(width: 6),
// Text('稍后再看', style: TextStyle(fontSize: 13))
// ],
// ),
// ),
// ],
// ),
// ),
// ], // ],
// ), // ),
], ],
@ -237,7 +280,7 @@ class VideoStat extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
height: 45, height: 48,
padding: const EdgeInsets.only(top: 22, left: 6, right: 6), padding: const EdgeInsets.only(top: 22, left: 6, right: 6),
decoration: const BoxDecoration( decoration: const BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(

View File

@ -58,14 +58,7 @@ class _BangumiPageState extends State<BangumiPage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
return Container( return RefreshIndicator(
clipBehavior: Clip.hardEdge,
margin: const EdgeInsets.only(
left: StyleString.safeSpace, right: StyleString.safeSpace),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(StyleString.imgRadius),
),
child: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await _bangumidController.queryBangumiListFeed(type: 'init'); await _bangumidController.queryBangumiListFeed(type: 'init');
return _bangumidController.queryBangumiFollow(); return _bangumidController.queryBangumiFollow();
@ -80,8 +73,8 @@ class _BangumiPageState extends State<BangumiPage>
child: Column( child: Column(
children: [ children: [
Padding( Padding(
padding: padding: const EdgeInsets.only(
const EdgeInsets.only(top: 10, bottom: 10, left: 6), top: StyleString.safeSpace, bottom: 10, left: 16),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -93,7 +86,7 @@ class _BangumiPageState extends State<BangumiPage>
), ),
), ),
SizedBox( SizedBox(
height: 254, height: 258,
child: FutureBuilder( child: FutureBuilder(
future: _bangumidController.queryBangumiFollow(), future: _bangumidController.queryBangumiFollow(),
builder: (context, snapshot) { builder: (context, snapshot) {
@ -111,7 +104,8 @@ class _BangumiPageState extends State<BangumiPage>
width: Get.size.width / 3, width: Get.size.width / 3,
height: 254, height: 254,
margin: EdgeInsets.only( margin: EdgeInsets.only(
right: index < left: StyleString.safeSpace,
right: index ==
_bangumidController _bangumidController
.bangumiFollowList .bangumiFollowList
.length - .length -
@ -142,7 +136,7 @@ class _BangumiPageState extends State<BangumiPage>
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10, left: 6), padding: const EdgeInsets.only(top: 10, bottom: 10, left: 16),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -155,15 +149,16 @@ class _BangumiPageState extends State<BangumiPage>
), ),
), ),
SliverPadding( SliverPadding(
padding: EdgeInsets.zero, padding: const EdgeInsets.fromLTRB(
StyleString.safeSpace, 0, StyleString.safeSpace, 0),
sliver: FutureBuilder( sliver: FutureBuilder(
future: _futureBuilderFuture, future: _futureBuilderFuture,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) { if (snapshot.connectionState == ConnectionState.done) {
Map data = snapshot.data as Map; Map data = snapshot.data as Map;
if (data['status']) { if (data['status']) {
return Obx(() => contentGrid(_bangumidController, return Obx(() => contentGrid(
_bangumidController.bangumiList)); _bangumidController, _bangumidController.bangumiList));
} else { } else {
return HttpError( return HttpError(
errMsg: data['msg'], errMsg: data['msg'],
@ -179,7 +174,6 @@ class _BangumiPageState extends State<BangumiPage>
const LoadingMore() const LoadingMore()
], ],
), ),
),
); );
} }

View File

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; 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/index.dart';
import 'package:pilipala/models/common/tab_type.dart'; import 'package:pilipala/models/common/tab_type.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
@ -12,7 +11,6 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
late TabController tabController; late TabController tabController;
late List tabsCtrList; late List tabsCtrList;
late List<Widget> tabsPageList; late List<Widget> tabsPageList;
RxString defaultSearch = '输入关键词搜索'.obs;
Box user = GStrorage.user; Box user = GStrorage.user;
RxBool userLogin = false.obs; RxBool userLogin = false.obs;
RxString userFace = ''.obs; RxString userFace = ''.obs;
@ -21,7 +19,6 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
void onInit() { void onInit() {
super.onInit(); super.onInit();
searchDefault();
userLogin.value = user.get(UserBoxKey.userLogin) ?? false; userLogin.value = user.get(UserBoxKey.userLogin) ?? false;
userFace.value = user.get(UserBoxKey.userFace) ?? ''; userFace.value = user.get(UserBoxKey.userFace) ?? '';
@ -49,13 +46,6 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
ctr().animateToTop(); ctr().animateToTop();
} }
void searchDefault() async {
var res = await Request().get(Api.searchDefault);
if (res.data['code'] == 0) {
defaultSearch.value = res.data['data']['name'];
}
}
// 更新登录状态 // 更新登录状态
void updateLoginStatus(val) { void updateLoginStatus(val) {
userLogin.value = val ?? false; userLogin.value = val ?? false;

View File

@ -1,12 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/pages/bangumi/index.dart';
import 'package:pilipala/pages/hot/index.dart';
import 'package:pilipala/pages/live/index.dart';
import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/main/index.dart';
import 'package:pilipala/pages/mine/index.dart'; import 'package:pilipala/pages/mine/index.dart';
import 'package:pilipala/pages/rcmd/index.dart'; import 'package:pilipala/pages/search/index.dart';
import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/feed_back.dart';
import './controller.dart'; import './controller.dart';
@ -53,49 +50,21 @@ class _HomePageState extends State<HomePage>
ctr: _homeController, ctr: _homeController,
callback: showUserBottonSheet, callback: showUserBottonSheet,
), ),
Padding( const SizedBox(height: 8),
padding: const EdgeInsets.only(left: 12, right: 12, bottom: 4), SizedBox(
child: Theme( width: double.infinity,
data: ThemeData( height: 42,
splashColor: Colors.transparent, // 点击时的水波纹颜色设置为透明 child: Align(
highlightColor: Colors.transparent, // 点击时的背景高亮颜色设置为透明 alignment: Alignment.center,
),
child: TabBar( child: TabBar(
controller: _homeController.tabController, controller: _homeController.tabController,
tabs: [ tabs: [
for (var i in _homeController.tabs) Tab(text: i['label']) for (var i in _homeController.tabs) Tab(text: i['label'])
], ],
isScrollable: true, isScrollable: true,
indicatorWeight: 0,
indicatorPadding: const EdgeInsets.only(
top: 37, left: 18, right: 18, bottom: 6),
indicatorColor: Colors.black,
indicator: BoxDecoration(
gradient: RadialGradient(
center: Alignment.centerLeft,
radius: 20.00,
colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.background,
],
),
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(4),
topRight: Radius.circular(2),
bottomLeft: Radius.circular(2),
bottomRight: Radius.circular(4),
),
),
indicatorSize: TabBarIndicatorSize.tab,
labelColor: Theme.of(context).colorScheme.primary,
labelStyle:
const TextStyle(fontSize: 13, fontWeight: FontWeight.bold),
dividerColor: Colors.transparent, dividerColor: Colors.transparent,
unselectedLabelStyle: TextStyle( enableFeedback: true,
color: Theme.of(context).colorScheme.outline, splashBorderRadius: BorderRadius.circular(10),
fontWeight: FontWeight.normal,
),
unselectedLabelColor: Theme.of(context).colorScheme.outline,
onTap: (value) { onTap: (value) {
feedBack(); feedBack();
if (_homeController.initialIndex == value) { if (_homeController.initialIndex == value) {
@ -141,83 +110,52 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
stream: stream, stream: stream,
initialData: true, initialData: true,
builder: (context, AsyncSnapshot snapshot) { builder: (context, AsyncSnapshot snapshot) {
return ClipRect( return AnimatedOpacity(
clipBehavior: Clip.hardEdge,
child: AnimatedOpacity(
opacity: snapshot.data ? 1 : 0, opacity: snapshot.data ? 1 : 0,
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
child: AnimatedContainer( child: AnimatedContainer(
curve: Curves.linear, curve: Curves.easeInOutCubicEmphasized,
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 500),
height: snapshot.data height: snapshot.data
? MediaQuery.of(context).padding.top + 42 ? MediaQuery.of(context).padding.top + 52
: MediaQuery.of(context).padding.top, : MediaQuery.of(context).padding.top,
child: Container( child: Container(
padding: EdgeInsets.only( padding: EdgeInsets.only(
left: 12, left: 20,
right: 12, right: 20,
bottom: 0, bottom: 0,
top: MediaQuery.of(context).padding.top, top: MediaQuery.of(context).padding.top + 4,
),
child: Row(children: [
Image.asset(
'assets/images/logo/logo_android_2.png',
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(width: 4),
Expanded(
child: GestureDetector(
onTap: () {
Get.toNamed('/search',
parameters: {'hintText': ctr!.defaultSearch.value});
},
child: Container(
width: 250,
height: 40,
clipBehavior: Clip.hardEdge,
padding: const EdgeInsets.only(left: 12, right: 22),
decoration: BoxDecoration(
borderRadius:
const BorderRadius.all(Radius.circular(25)),
color: Theme.of(context).colorScheme.onInverseSurface,
), ),
child: Row( child: Row(
children: [ children: [
Icon( const Expanded(child: SearchPage()),
Icons.search_outlined,
size: 21,
color: Theme.of(context).colorScheme.outline,
),
const SizedBox(width: 6),
Expanded(
child: Obx(
() => Text(
ctr!.defaultSearch.value,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.outline),
),
),
),
],
),
),
),
),
const SizedBox(width: 10), const SizedBox(width: 10),
Obx( Obx(
() => ctr!.userLogin.value () => ctr!.userLogin.value
? GestureDetector( ? Stack(
onTap: () => callback!(), children: [
child: NetworkImgLayer( NetworkImgLayer(
type: 'avatar', type: 'avatar',
width: 38, width: 34,
height: 38, height: 34,
src: ctr!.userFace.value, src: ctr!.userFace.value,
), ),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => callback!(),
splashColor: Theme.of(context)
.colorScheme
.primaryContainer
.withOpacity(0.3),
borderRadius: const BorderRadius.all(
Radius.circular(50),
),
),
),
)
],
) )
: SizedBox( : SizedBox(
width: 38, width: 38,
@ -242,7 +180,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
), ),
), ),
), ),
]), ],
), ),
), ),
), ),

View File

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/animated_dialog.dart'; import 'package:pilipala/common/widgets/animated_dialog.dart';
import 'package:pilipala/common/widgets/overlay_pop.dart'; import 'package:pilipala/common/widgets/overlay_pop.dart';
import 'package:pilipala/common/skeleton/video_card_h.dart'; import 'package:pilipala/common/skeleton/video_card_h.dart';
@ -59,14 +60,17 @@ class _HotPageState extends State<HotPage> with AutomaticKeepAliveClientMixin {
super.build(context); super.build(context);
return Scaffold( return Scaffold(
body: RefreshIndicator( body: RefreshIndicator(
displacement: kToolbarHeight + MediaQuery.of(context).padding.top,
onRefresh: () async { onRefresh: () async {
return await _hotController.onRefresh(); return await _hotController.onRefresh();
}, },
child: CustomScrollView( child: CustomScrollView(
controller: _hotController.scrollController, controller: _hotController.scrollController,
slivers: [ slivers: [
FutureBuilder( SliverPadding(
// 单列布局 EdgeInsets.zero
padding:
const EdgeInsets.fromLTRB(0, StyleString.safeSpace - 5, 0, 0),
sliver: FutureBuilder(
future: _futureBuilderFuture, future: _futureBuilderFuture,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) { if (snapshot.connectionState == ConnectionState.done) {
@ -74,7 +78,8 @@ class _HotPageState extends State<HotPage> with AutomaticKeepAliveClientMixin {
if (data['status']) { if (data['status']) {
return Obx( return Obx(
() => SliverList( () => SliverList(
delegate: SliverChildBuilderDelegate((context, index) { delegate:
SliverChildBuilderDelegate((context, index) {
return VideoCardH( return VideoCardH(
videoItem: _hotController.videoList[index], videoItem: _hotController.videoList[index],
longPress: () { longPress: () {
@ -106,6 +111,7 @@ class _HotPageState extends State<HotPage> with AutomaticKeepAliveClientMixin {
} }
}, },
), ),
),
SliverToBoxAdapter( SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
height: MediaQuery.of(context).padding.bottom + 10, height: MediaQuery.of(context).padding.bottom + 10,

View File

@ -70,7 +70,8 @@ class _LivePageState extends State<LivePage> {
slivers: [ slivers: [
SliverPadding( SliverPadding(
// 单列布局 EdgeInsets.zero // 单列布局 EdgeInsets.zero
padding: EdgeInsets.zero, padding:
const EdgeInsets.fromLTRB(0, StyleString.safeSpace, 0, 0),
sliver: FutureBuilder( sliver: FutureBuilder(
future: _liveController.queryLiveList('init'), future: _liveController.queryLiveList('init'),
builder: (context, snapshot) { builder: (context, snapshot) {
@ -118,13 +119,13 @@ class _LivePageState extends State<LivePage> {
return SliverGrid( return SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 行间距 // 行间距
mainAxisSpacing: StyleString.cardSpace + 2, mainAxisSpacing: StyleString.cardSpace + 4,
// 列间距 // 列间距
crossAxisSpacing: StyleString.cardSpace + 3, crossAxisSpacing: StyleString.cardSpace + 4,
// 列数 // 列数
crossAxisCount: ctr.crossAxisCount, crossAxisCount: ctr.crossAxisCount,
mainAxisExtent: mainAxisExtent:
Get.size.width / ctr.crossAxisCount / StyleString.aspectRatio + 60, Get.size.width / ctr.crossAxisCount / StyleString.aspectRatio + 64,
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {

View File

@ -103,7 +103,7 @@ class LiveContent extends StatelessWidget {
return Expanded( return Expanded(
child: Padding( child: Padding(
// 多列 // 多列
padding: const EdgeInsets.fromLTRB(4, 5, 6, 6), padding: const EdgeInsets.fromLTRB(4, 8, 0, 6),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -154,7 +154,7 @@ class VideoStat extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
height: 45, height: 50,
padding: const EdgeInsets.only(top: 22, left: 10, right: 10), padding: const EdgeInsets.only(top: 22, left: 10, right: 10),
decoration: const BoxDecoration( decoration: const BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(

View File

@ -15,23 +15,35 @@ class MainController extends GetxController {
RxList navigationBars = [ RxList navigationBars = [
{ {
'icon': const Icon( 'icon': const Icon(
Icons.motion_photos_on_outlined, Icons.favorite_outline,
size: 21, size: 21,
), ),
'label': "推荐", 'selectIcon': const Icon(
Icons.favorite,
size: 21,
),
'label': "首页",
}, },
{ {
'icon': const Icon( 'icon': const Icon(
Icons.bolt, Icons.motion_photos_on_outlined,
size: 21,
),
'selectIcon': const Icon(
Icons.motion_photos_on,
size: 21, size: 21,
), ),
'label': "动态", 'label': "动态",
}, },
{ {
'icon': const Icon( 'icon': const Icon(
Icons.folder_open_outlined, Icons.folder_outlined,
size: 20, size: 20,
), ),
'selectIcon': const Icon(
Icons.folder,
size: 21,
),
'label': "媒体库", 'label': "媒体库",
} }
].obs; ].obs;

View File

@ -135,21 +135,17 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
initialData: true, initialData: true,
builder: (context, AsyncSnapshot snapshot) { builder: (context, AsyncSnapshot snapshot) {
return AnimatedSlide( return AnimatedSlide(
curve: Curves.linear, curve: Curves.easeInOutCubicEmphasized,
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 1000),
offset: Offset(0, snapshot.data ? 0 : 1), offset: Offset(0, snapshot.data ? 0 : 1),
child: BottomNavigationBar( child: NavigationBar(
currentIndex: selectedIndex, onDestinationSelected: (value) => setIndex(value),
// type: BottomNavigationBarType.shifting, selectedIndex: selectedIndex,
selectedItemColor: Theme.of(context).colorScheme.primary, destinations: <Widget>[
unselectedItemColor:
Theme.of(context).colorScheme.outline.withOpacity(0.5),
selectedFontSize: 12.4,
onTap: (value) => setIndex(value),
items: [
..._mainController.navigationBars.map((e) { ..._mainController.navigationBars.map((e) {
return BottomNavigationBarItem( return NavigationDestination(
icon: e['icon'], icon: e['icon'],
selectedIcon: e['selectIcon'],
label: e['label'], label: e['label'],
); );
}).toList(), }).toList(),

View File

@ -77,7 +77,7 @@ class _RcmdPageState extends State<RcmdPage>
// 单列布局 EdgeInsets.zero // 单列布局 EdgeInsets.zero
padding: _rcmdController.crossAxisCount == 1 padding: _rcmdController.crossAxisCount == 1
? EdgeInsets.zero ? EdgeInsets.zero
: const EdgeInsets.fromLTRB(0, 0, 0, 0), : const EdgeInsets.fromLTRB(0, StyleString.safeSpace, 0, 0),
sliver: FutureBuilder( sliver: FutureBuilder(
future: _rcmdController.queryRcmdFeed('init'), future: _rcmdController.queryRcmdFeed('init'),
builder: (context, snapshot) { builder: (context, snapshot) {
@ -124,13 +124,13 @@ class _RcmdPageState extends State<RcmdPage>
return SliverGrid( return SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 行间距 // 行间距
mainAxisSpacing: StyleString.cardSpace + 2, mainAxisSpacing: StyleString.cardSpace + 4,
// 列间距 // 列间距
crossAxisSpacing: StyleString.cardSpace + 3, crossAxisSpacing: StyleString.cardSpace + 4,
// 列数 // 列数
crossAxisCount: ctr.crossAxisCount, crossAxisCount: ctr.crossAxisCount,
mainAxisExtent: mainAxisExtent:
Get.size.width / ctr.crossAxisCount / StyleString.aspectRatio + 60, Get.size.width / ctr.crossAxisCount / StyleString.aspectRatio + 64,
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:pilipala/http/index.dart';
import 'package:pilipala/http/search.dart'; import 'package:pilipala/http/search.dart';
import 'package:pilipala/models/search/hot.dart'; import 'package:pilipala/models/search/hot.dart';
import 'package:pilipala/models/search/suggest.dart'; import 'package:pilipala/models/search/suggest.dart';
@ -20,10 +21,12 @@ class SSearchController extends GetxController {
final _debouncer = final _debouncer =
Debouncer(delay: const Duration(milliseconds: 200)); // 设置延迟时间 Debouncer(delay: const Duration(milliseconds: 200)); // 设置延迟时间
String hintText = '搜索'; String hintText = '搜索';
RxString defaultSearch = '输入关键词搜索'.obs;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
searchDefault();
if (hotKeyword.get('cacheList') != null && if (hotKeyword.get('cacheList') != null &&
hotKeyword.get('cacheList').isNotEmpty) { hotKeyword.get('cacheList').isNotEmpty) {
List<HotSearchItem> list = []; List<HotSearchItem> list = [];
@ -121,4 +124,12 @@ class SSearchController extends GetxController {
historyList.refresh(); historyList.refresh();
histiryWord.put('cacheList', []); histiryWord.put('cacheList', []);
} }
void searchDefault() async {
var res = await Request().get(Api.searchDefault);
if (res.data['code'] == 0) {
searchKeyWord.value =
hintText = defaultSearch.value = res.data['data']['name'];
}
}
} }

View File

@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/http_error.dart';
import 'controller.dart'; import 'controller.dart';
@ -41,6 +42,60 @@ class _SearchPageState extends State<SearchPage> with RouteAware {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return OpenContainer(
closedElevation: 0,
openElevation: 0,
openColor: Theme.of(context).colorScheme.background,
middleColor: Theme.of(context).colorScheme.background,
closedColor: Theme.of(context).colorScheme.background,
closedShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(30.0))),
openShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(30.0))),
closedBuilder: (BuildContext context, VoidCallback openContainer) {
return Container(
width: 250,
height: 44,
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(25)),
),
child: Material(
color:
Theme.of(context).colorScheme.secondaryContainer.withAlpha(115),
child: InkWell(
splashColor: Theme.of(context)
.colorScheme
.primaryContainer
.withOpacity(0.3),
onTap: openContainer,
child: Row(
children: [
const SizedBox(width: 14),
Icon(
Icons.search_outlined,
color: Theme.of(context).colorScheme.onSecondaryContainer,
),
const SizedBox(width: 10),
Expanded(
child: Obx(
() => Text(
_searchController.defaultSearch.value,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context).colorScheme.outline,
),
),
),
),
],
),
),
),
);
},
openBuilder: (BuildContext context, VoidCallback _) {
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
@ -97,6 +152,8 @@ class _SearchPageState extends State<SearchPage> with RouteAware {
), ),
), ),
); );
},
);
} }
Widget _searchSuggest() { Widget _searchSuggest() {

View File

@ -105,7 +105,8 @@ class _FavPanelState extends State<FavPanel> {
left: 20, left: 20,
right: 20, right: 20,
top: 12, top: 12,
bottom: MediaQuery.of(context).padding.bottom), bottom: MediaQuery.of(context).padding.bottom + 12,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [

View File

@ -31,6 +31,10 @@ class GStrorage {
localCache = await Hive.openBox('localCache'); localCache = await Hive.openBox('localCache');
// 设置 // 设置
setting = await Hive.openBox('setting'); setting = await Hive.openBox('setting');
// 热搜关键词
hotKeyword = await Hive.openBox('hotKeyword');
// 搜索历史
historyword = await Hive.openBox('historyWord');
} }
static regAdapter() { static regAdapter() {
@ -45,10 +49,6 @@ class GStrorage {
} }
static Future<void> lazyInit() async { static Future<void> lazyInit() async {
// 热搜关键词
hotKeyword = await Hive.openBox('hotKeyword');
// 搜索历史
historyword = await Hive.openBox('historyWord');
// 视频设置 // 视频设置
video = await Hive.openBox('video'); video = await Hive.openBox('video');
} }

View File

@ -17,6 +17,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.13.0" version: "5.13.0"
animations:
dependency: "direct main"
description:
name: animations
sha256: fe8a6bdca435f718bb1dc8a11661b2c22504c6da40ef934cee8327ed77934164
url: "https://pub.dev"
source: hosted
version: "2.0.7"
archive: archive:
dependency: transitive dependency: transitive
description: description:

View File

@ -107,6 +107,7 @@ dependencies:
universal_platform: ^1.0.0+1 universal_platform: ^1.0.0+1
# 进度条 # 进度条
audio_video_progress_bar: ^1.0.1 audio_video_progress_bar: ^1.0.1
animations: ^2.0.7
# auto_orientation: ^2.3.1 # auto_orientation: ^2.3.1
dev_dependencies: dev_dependencies: