feat: 收藏夹
This commit is contained in:
3
lib/pages/fav/controller.dart
Normal file
3
lib/pages/fav/controller.dart
Normal file
@ -0,0 +1,3 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class FavController extends GetxController {}
|
||||
4
lib/pages/fav/index.dart
Normal file
4
lib/pages/fav/index.dart
Normal file
@ -0,0 +1,4 @@
|
||||
library fav;
|
||||
|
||||
export './controller.dart';
|
||||
export './view.dart';
|
||||
20
lib/pages/fav/view.dart
Normal file
20
lib/pages/fav/view.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FavPage extends StatefulWidget {
|
||||
const FavPage({super.key});
|
||||
|
||||
@override
|
||||
State<FavPage> createState() => _FavPageState();
|
||||
}
|
||||
|
||||
class _FavPageState extends State<FavPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: false,
|
||||
title: Text('我的收藏'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,8 @@ import 'dart:io';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/pages/mine/view.dart';
|
||||
|
||||
class HomeAppBar extends StatelessWidget {
|
||||
const HomeAppBar({super.key});
|
||||
@ -42,6 +44,12 @@ class HomeAppBar extends StatelessWidget {
|
||||
// onPressed: () {},
|
||||
// icon: const Icon(CupertinoIcons.bell, size: 22),
|
||||
// ),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(const MinePage());
|
||||
},
|
||||
icon: const Icon(CupertinoIcons.person, size: 22),
|
||||
),
|
||||
const SizedBox(width: 10)
|
||||
],
|
||||
elevation: 0,
|
||||
|
||||
@ -5,26 +5,26 @@ import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/pages/home/view.dart';
|
||||
import 'package:pilipala/pages/hot/view.dart';
|
||||
import 'package:pilipala/pages/mine/view.dart';
|
||||
import 'package:pilipala/pages/media/index.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
|
||||
class MainController extends GetxController {
|
||||
List<Widget> pages = <Widget>[
|
||||
const HomePage(),
|
||||
const HotPage(),
|
||||
const MinePage(),
|
||||
const MediaPage(),
|
||||
];
|
||||
RxList navigationBars = [
|
||||
{
|
||||
// 'icon': const Icon(Icons.home_outlined),
|
||||
// 'selectedIcon': const Icon(Icons.home),
|
||||
'icon': const Icon(
|
||||
CupertinoIcons.house,
|
||||
size: 18,
|
||||
CupertinoIcons.square_favorites_alt,
|
||||
size: 21,
|
||||
),
|
||||
'selectedIcon': const Icon(
|
||||
CupertinoIcons.house_fill,
|
||||
size: 18,
|
||||
CupertinoIcons.square_favorites_alt_fill,
|
||||
size: 21,
|
||||
),
|
||||
'label': "推荐",
|
||||
},
|
||||
@ -41,46 +41,57 @@ class MainController extends GetxController {
|
||||
),
|
||||
'label': "热门",
|
||||
},
|
||||
// {
|
||||
// 'icon': const Icon(
|
||||
// CupertinoIcons.person,
|
||||
// size: 21,
|
||||
// ),
|
||||
// 'selectedIcon': const Icon(
|
||||
// CupertinoIcons.person_fill,
|
||||
// size: 21,
|
||||
// ),
|
||||
// 'label': "我的",
|
||||
// },
|
||||
{
|
||||
// 'icon': const Icon(Icons.person_outline),
|
||||
// 'selectedIcon': const Icon(Icons.person),
|
||||
'icon': const Icon(
|
||||
CupertinoIcons.person,
|
||||
CupertinoIcons.tray_full,
|
||||
size: 21,
|
||||
),
|
||||
'selectedIcon': const Icon(
|
||||
CupertinoIcons.person_fill,
|
||||
CupertinoIcons.tray_full_fill,
|
||||
size: 21,
|
||||
),
|
||||
'label': "我的",
|
||||
'label': "媒体库",
|
||||
}
|
||||
].obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
readuUserFace();
|
||||
// readuUserFace();
|
||||
}
|
||||
|
||||
// 设置头像
|
||||
readuUserFace() async {
|
||||
Box user = GStrorage.user;
|
||||
if (user.get(UserBoxKey.userFace) != null) {
|
||||
navigationBars.last['icon'] =
|
||||
navigationBars.last['selectedIcon'] = NetworkImgLayer(
|
||||
width: 25,
|
||||
height: 25,
|
||||
type: 'avatar',
|
||||
src: user.get(UserBoxKey.userFace),
|
||||
);
|
||||
navigationBars.last['label'] = '我';
|
||||
}
|
||||
}
|
||||
// readuUserFace() async {
|
||||
// Box user = GStrorage.user;
|
||||
// if (user.get(UserBoxKey.userFace) != null) {
|
||||
// navigationBars.last['icon'] =
|
||||
// navigationBars.last['selectedIcon'] = NetworkImgLayer(
|
||||
// width: 25,
|
||||
// height: 25,
|
||||
// type: 'avatar',
|
||||
// src: user.get(UserBoxKey.userFace),
|
||||
// );
|
||||
// navigationBars.last['label'] = '我';
|
||||
// }
|
||||
// }
|
||||
|
||||
// 重置
|
||||
resetLast() {
|
||||
navigationBars.last['icon'] = const Icon(Icons.person_outline);
|
||||
navigationBars.last['selectedIcon'] = const Icon(Icons.person);
|
||||
navigationBars.last['label'] = '我的';
|
||||
}
|
||||
// resetLast() {
|
||||
// navigationBars.last['icon'] = const Icon(Icons.person_outline);
|
||||
// navigationBars.last['selectedIcon'] = const Icon(Icons.person);
|
||||
// navigationBars.last['label'] = '我的';
|
||||
// }
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
||||
late AnimationController? _animationController;
|
||||
late Animation<double>? _fadeAnimation;
|
||||
late Animation<double>? _slideAnimation;
|
||||
int selectedIndex = 2;
|
||||
int selectedIndex = 0;
|
||||
int? _lastSelectTime; //上次点击时间
|
||||
|
||||
@override
|
||||
|
||||
41
lib/pages/media/controller.dart
Normal file
41
lib/pages/media/controller.dart
Normal file
@ -0,0 +1,41 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/user.dart';
|
||||
import 'package:pilipala/models/user/fav_folder.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
|
||||
class MediaController extends GetxController {
|
||||
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
||||
List list = [
|
||||
{
|
||||
'icon': Icons.file_download_outlined,
|
||||
'title': '离线缓存',
|
||||
'onTap': () => Get.toNamed('/fav'),
|
||||
},
|
||||
{
|
||||
'icon': Icons.history,
|
||||
'title': '观看记录',
|
||||
'onTap': () => Get.toNamed('/fav'),
|
||||
},
|
||||
{
|
||||
'icon': Icons.star_border,
|
||||
'title': '我的收藏',
|
||||
'onTap': () => Get.toNamed('/fav'),
|
||||
},
|
||||
{
|
||||
'icon': Icons.watch_later_outlined,
|
||||
'title': '稍后再看',
|
||||
'onTap': () => Get.toNamed('/fav'),
|
||||
},
|
||||
];
|
||||
|
||||
Future<dynamic> queryFavFolder() async {
|
||||
var res = await await UserHttp.userfavFolder(
|
||||
pn: 1,
|
||||
ps: 5,
|
||||
mid: GStrorage.user.get(UserBoxKey.userMid),
|
||||
);
|
||||
favFolderData.value = res['data'];
|
||||
return res;
|
||||
}
|
||||
}
|
||||
4
lib/pages/media/index.dart
Normal file
4
lib/pages/media/index.dart
Normal file
@ -0,0 +1,4 @@
|
||||
library media;
|
||||
|
||||
export './controller.dart';
|
||||
export './view.dart';
|
||||
214
lib/pages/media/view.dart
Normal file
214
lib/pages/media/view.dart
Normal file
@ -0,0 +1,214 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/models/user/fav_folder.dart';
|
||||
import 'package:pilipala/pages/media/index.dart';
|
||||
|
||||
class MediaPage extends StatefulWidget {
|
||||
const MediaPage({super.key});
|
||||
|
||||
@override
|
||||
State<MediaPage> createState() => _MediaPageState();
|
||||
}
|
||||
|
||||
class _MediaPageState extends State<MediaPage>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
final MediaController _mediaController = Get.put(MediaController());
|
||||
Future? _futureBuilderFuture;
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_futureBuilderFuture = _mediaController.queryFavFolder();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color primary = Theme.of(context).colorScheme.primary;
|
||||
return Scaffold(
|
||||
appBar: AppBar(toolbarHeight: 30),
|
||||
body: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: null,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(left: 20),
|
||||
child: Text(
|
||||
'媒体库',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.titleLarge!.fontSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
for (var i in _mediaController.list) ...[
|
||||
ListTile(
|
||||
onTap: () => i['onTap'](),
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: Icon(
|
||||
i['icon'],
|
||||
color: primary,
|
||||
),
|
||||
),
|
||||
minLeadingWidth: 0,
|
||||
title: Text(i['title']),
|
||||
),
|
||||
],
|
||||
favFolder()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget favFolder() {
|
||||
return Column(
|
||||
children: [
|
||||
Divider(
|
||||
height: 35,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {},
|
||||
leading: null,
|
||||
dense: true,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: Obx(
|
||||
() => Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '收藏夹 ',
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.titleMedium!.fontSize,
|
||||
),
|
||||
),
|
||||
if (_mediaController.favFolderData.value.count != null)
|
||||
TextSpan(
|
||||
text: _mediaController.favFolderData.value.count
|
||||
.toString(),
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.titleSmall!.fontSize,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
trailing: Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
'查看全部',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
),
|
||||
// const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 170,
|
||||
child: ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: [
|
||||
const SizedBox(width: 20),
|
||||
FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
Map data = snapshot.data;
|
||||
if (data['status']) {
|
||||
return Obx(() => Row(
|
||||
children: [
|
||||
if (_mediaController.favFolderData.value.list !=
|
||||
null) ...[
|
||||
for (FavFolderItemData i in _mediaController
|
||||
.favFolderData.value.list!) ...[
|
||||
FavFolderItem(item: i),
|
||||
const SizedBox(width: 14)
|
||||
]
|
||||
]
|
||||
],
|
||||
));
|
||||
} else {
|
||||
return SizedBox(
|
||||
height: 160,
|
||||
child: Center(child: Text(data['msg'])),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// 骨架屏
|
||||
return SizedBox();
|
||||
}
|
||||
}),
|
||||
// for (var i in [1, 2, 3]) ...[const FavFolderItem()],
|
||||
const SizedBox(width: 10)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FavFolderItem extends StatelessWidget {
|
||||
FavFolderItem({super.key, this.item});
|
||||
FavFolderItemData? item;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
width: 110 * 16 / 9,
|
||||
height: 110,
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
offset: const Offset(4, -12), // 阴影与容器的距离
|
||||
blurRadius: 0.0, // 高斯的标准偏差与盒子的形状卷积。
|
||||
spreadRadius: 0.0, // 在应用模糊之前,框应该膨胀的量。
|
||||
),
|
||||
],
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, BoxConstraints box) {
|
||||
return NetworkImgLayer(
|
||||
src: item!.cover,
|
||||
width: box.maxWidth,
|
||||
height: box.maxHeight,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Text(
|
||||
' ${item!.title}',
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 1,
|
||||
),
|
||||
Text(
|
||||
' 共${item!.mediaCount}条视频',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,7 @@ class MineController extends GetxController {
|
||||
user.put(UserBoxKey.userMid, res['data'].mid);
|
||||
user.put(UserBoxKey.userLogin, true);
|
||||
userLogin.value = true;
|
||||
Get.find<MainController>().readuUserFace();
|
||||
// Get.find<MainController>().readuUserFace();
|
||||
} else {
|
||||
resetUserInfo();
|
||||
}
|
||||
@ -64,6 +64,6 @@ class MineController extends GetxController {
|
||||
await user.delete(UserBoxKey.userMid);
|
||||
await user.delete(UserBoxKey.userLogin);
|
||||
userLogin.value = false;
|
||||
Get.find<MainController>().resetLast();
|
||||
// Get.find<MainController>().resetLast();
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,11 @@ class _MinePageState extends State<MinePage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
scrolledUnderElevation: 0,
|
||||
elevation: 0,
|
||||
toolbarHeight: kTextTabBarHeight + 20,
|
||||
backgroundColor: Colors.transparent,
|
||||
title: null,
|
||||
actions: [
|
||||
IconButton(
|
||||
@ -54,6 +59,7 @@ class _MinePageState extends State<MinePage> {
|
||||
height: constraint.maxHeight,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
FutureBuilder(
|
||||
future: _mineController.queryUserInfo(),
|
||||
builder: (context, snapshot) {
|
||||
@ -69,45 +75,6 @@ class _MinePageState extends State<MinePage> {
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 12, right: 12),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return SizedBox(
|
||||
height: constraints.maxWidth / 4 * 0.8,
|
||||
child: GridView.count(
|
||||
primary: false,
|
||||
padding: const EdgeInsets.all(0),
|
||||
crossAxisCount: 4,
|
||||
childAspectRatio: 1.25,
|
||||
children: <Widget>[
|
||||
ActionItem(
|
||||
icon:
|
||||
const Icon(CupertinoIcons.cloud_download),
|
||||
onTap: () => {},
|
||||
text: '离线缓存',
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(CupertinoIcons.time),
|
||||
onTap: () => {},
|
||||
text: '历史记录',
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(CupertinoIcons.star),
|
||||
onTap: () => {},
|
||||
text: '我的收藏',
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(CupertinoIcons.film),
|
||||
onTap: () => {},
|
||||
text: '稍后再看',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user