Merge branch 'main' into fix

This commit is contained in:
guozhigq
2024-07-07 11:01:29 +08:00
21 changed files with 285 additions and 236 deletions

View File

@ -9,11 +9,18 @@ class MemberSeasonsDataModel {
MemberSeasonsDataModel.fromJson(Map<String, dynamic> json) { MemberSeasonsDataModel.fromJson(Map<String, dynamic> json) {
page = json['page']; page = json['page'];
seasonsList = json['seasons_list'] != null var tempList1 = json['seasons_list'] != null
? json['seasons_list'] ? json['seasons_list']
.map<MemberSeasonsList>((e) => MemberSeasonsList.fromJson(e)) .map<MemberSeasonsList>((e) => MemberSeasonsList.fromJson(e))
.toList() .toList()
: []; : [];
var tempList2 = json['series_list'] != null
? json['series_list']
.map<MemberSeasonsList>((e) => MemberSeasonsList.fromJson(e))
.toList()
: [];
seasonsList = [...tempList1, ...tempList2];
} }
} }

View File

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:custom_sliding_segmented_control/custom_sliding_segmented_control.dart'; import 'package:custom_sliding_segmented_control/custom_sliding_segmented_control.dart';
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/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:pilipala/common/skeleton/dynamic_card.dart'; import 'package:pilipala/common/skeleton/dynamic_card.dart';
@ -77,10 +78,14 @@ class _DynamicsPageState extends State<DynamicsPage>
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
return Scaffold( return Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar( appBar: AppBar(
elevation: 0, elevation: 0,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
titleSpacing: 0, backgroundColor: Colors.transparent,
systemOverlayStyle: Theme.of(context).brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark,
title: SizedBox( title: SizedBox(
height: 34, height: 34,
child: Stack( child: Stack(

View File

@ -16,10 +16,16 @@ class FavController extends GetxController {
int currentPage = 1; int currentPage = 1;
int pageSize = 60; int pageSize = 60;
RxBool hasMore = true.obs; RxBool hasMore = true.obs;
late int mid;
late int ownerMid;
RxBool isOwner = false.obs;
@override @override
void onInit() { void onInit() {
mid = int.parse(Get.parameters['mid'] ?? '-1');
userInfo = userInfoCache.get('userInfoCache'); userInfo = userInfoCache.get('userInfoCache');
ownerMid = userInfo != null ? userInfo!.mid! : -1;
isOwner.value = mid == -1 || mid == ownerMid;
super.onInit(); super.onInit();
} }
@ -33,7 +39,7 @@ class FavController extends GetxController {
var res = await UserHttp.userfavFolder( var res = await UserHttp.userfavFolder(
pn: currentPage, pn: currentPage,
ps: pageSize, ps: pageSize,
mid: userInfo!.mid!, mid: isOwner.value ? ownerMid : mid,
); );
if (res['status']) { if (res['status']) {
if (type == 'init') { if (type == 'init') {

View File

@ -42,17 +42,25 @@ class _FavPageState extends State<FavPage> {
appBar: AppBar( appBar: AppBar(
centerTitle: false, centerTitle: false,
titleSpacing: 0, titleSpacing: 0,
title: Text( title: Obx(() => Text(
'的收藏', '${_favController.isOwner.value ? '' : 'Ta'}的收藏',
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), )),
actions: [ actions: [
Obx(() => !_favController.isOwner.value
? IconButton(
onPressed: () =>
Get.toNamed('/subscription?mid=${_favController.mid}'),
icon: const Icon(Icons.subscriptions_outlined, size: 21),
tooltip: 'Ta的订阅',
)
: const SizedBox.shrink()),
IconButton( IconButton(
onPressed: () => Get.toNamed( onPressed: () => Get.toNamed(
'/favSearch?searchType=1&mediaId=${_favController.favFolderData.value.list!.first.id}'), '/favSearch?searchType=1&mediaId=${_favController.favFolderData.value.list!.first.id}'),
icon: const Icon(Icons.search_outlined), icon: const Icon(Icons.search_outlined),
), ),
const SizedBox(width: 6), const SizedBox(width: 14),
], ],
), ),
body: FutureBuilder( body: FutureBuilder(
@ -67,7 +75,9 @@ class _FavPageState extends State<FavPage> {
itemCount: _favController.favFolderList.length, itemCount: _favController.favFolderList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return FavItem( return FavItem(
favFolderItem: _favController.favFolderList[index]); favFolderItem: _favController.favFolderList[index],
isOwner: _favController.isOwner.value,
);
}, },
), ),
); );

View File

@ -7,7 +7,9 @@ import 'package:pilipala/utils/utils.dart';
class FavItem extends StatelessWidget { class FavItem extends StatelessWidget {
// ignore: prefer_typing_uninitialized_variables // ignore: prefer_typing_uninitialized_variables
final favFolderItem; final favFolderItem;
const FavItem({super.key, required this.favFolderItem}); final bool isOwner;
const FavItem(
{super.key, required this.favFolderItem, required this.isOwner});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -20,6 +22,7 @@ class FavItem extends StatelessWidget {
parameters: { parameters: {
'heroTag': heroTag, 'heroTag': heroTag,
'mediaId': favFolderItem.id.toString(), 'mediaId': favFolderItem.id.toString(),
'isOwner': isOwner ? '1' : '0',
}, },
); );
}, },

View File

@ -19,6 +19,7 @@ class FavDetailController extends GetxController {
RxList favList = [].obs; RxList favList = [].obs;
RxString loadingText = '加载中...'.obs; RxString loadingText = '加载中...'.obs;
RxInt mediaCount = 0.obs; RxInt mediaCount = 0.obs;
late String isOwner;
@override @override
void onInit() { void onInit() {
@ -26,6 +27,7 @@ class FavDetailController extends GetxController {
if (Get.parameters.keys.isNotEmpty) { if (Get.parameters.keys.isNotEmpty) {
mediaId = int.parse(Get.parameters['mediaId']!); mediaId = int.parse(Get.parameters['mediaId']!);
heroTag = Get.parameters['heroTag']!; heroTag = Get.parameters['heroTag']!;
isOwner = Get.parameters['isOwner']!;
} }
super.onInit(); super.onInit();
} }

View File

@ -212,6 +212,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
SliverChildBuilderDelegate((context, index) { SliverChildBuilderDelegate((context, index) {
return FavVideoCardH( return FavVideoCardH(
videoItem: favList[index], videoItem: favList[index],
isOwner: _favDetailController.isOwner,
callFn: () => _favDetailController callFn: () => _favDetailController
.onCancelFav(favList[index].id), .onCancelFav(favList[index].id),
); );

View File

@ -18,12 +18,14 @@ class FavVideoCardH extends StatelessWidget {
final dynamic videoItem; final dynamic videoItem;
final Function? callFn; final Function? callFn;
final int? searchType; final int? searchType;
final String isOwner;
const FavVideoCardH({ const FavVideoCardH({
Key? key, Key? key,
required this.videoItem, required this.videoItem,
this.callFn, this.callFn,
this.searchType, this.searchType,
required this.isOwner,
}) : super(key: key); }) : super(key: key);
@override @override
@ -123,6 +125,7 @@ class FavVideoCardH extends StatelessWidget {
videoItem: videoItem, videoItem: videoItem,
callFn: callFn, callFn: callFn,
searchType: searchType, searchType: searchType,
isOwner: isOwner,
) )
], ],
), ),
@ -140,11 +143,13 @@ class VideoContent extends StatelessWidget {
final dynamic videoItem; final dynamic videoItem;
final Function? callFn; final Function? callFn;
final int? searchType; final int? searchType;
final String isOwner;
const VideoContent({ const VideoContent({
super.key, super.key,
required this.videoItem, required this.videoItem,
this.callFn, this.callFn,
this.searchType, this.searchType,
required this.isOwner,
}); });
@override @override
@ -211,7 +216,7 @@ class VideoContent extends StatelessWidget {
), ),
], ],
), ),
searchType != 1 searchType != 1 && isOwner == '1'
? Positioned( ? Positioned(
right: 0, right: 0,
bottom: -4, bottom: -4,

View File

@ -100,6 +100,7 @@ class _FavSearchPageState extends State<FavSearchPage> {
return FavVideoCardH( return FavVideoCardH(
videoItem: _favSearchCtr.favList[index], videoItem: _favSearchCtr.favList[index],
searchType: searchType, searchType: searchType,
isOwner: '0',
callFn: () => searchType != 1 callFn: () => searchType != 1
? _favSearchCtr ? _favSearchCtr
.onCancelFav(_favSearchCtr.favList[index].id!) .onCancelFav(_favSearchCtr.favList[index].id!)

View File

@ -46,104 +46,66 @@ class _HomePageState extends State<HomePage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
Brightness currentBrightness = MediaQuery.of(context).platformBrightness;
// 设置状态栏图标的亮度
if (_homeController.enableGradientBg) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarIconBrightness: currentBrightness == Brightness.light
? Brightness.dark
: Brightness.light,
));
}
return Scaffold( return Scaffold(
extendBody: true, extendBody: true,
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: _homeController.enableGradientBg backgroundColor: Colors.transparent,
? null appBar: AppBar(
: AppBar(toolbarHeight: 0, elevation: 0), toolbarHeight: 0,
body: Stack( elevation: 0,
backgroundColor: Colors.transparent,
systemOverlayStyle: Theme.of(context).brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark,
),
body: Column(
children: [ children: [
// gradient background CustomAppBar(
if (_homeController.enableGradientBg) ...[ stream: _homeController.hideSearchBar
Align( ? stream
alignment: Alignment.topLeft, : StreamController<bool>.broadcast().stream,
child: Opacity( ctr: _homeController,
opacity: 0.6, callback: showUserBottomSheet,
child: Container( ),
width: MediaQuery.of(context).size.width, if (_homeController.tabs.length > 1) ...[
height: MediaQuery.of(context).size.height, if (_homeController.enableGradientBg) ...[
decoration: BoxDecoration( const CustomTabs(),
gradient: LinearGradient( ] else ...[
colors: [ Container(
Theme.of(context) width: double.infinity,
.colorScheme height: 42,
.primary padding: const EdgeInsets.only(top: 4),
.withOpacity(0.9), child: Align(
Theme.of(context) alignment: Alignment.center,
.colorScheme child: TabBar(
.primary controller: _homeController.tabController,
.withOpacity(0.5), tabs: [
Theme.of(context).colorScheme.surface for (var i in _homeController.tabs) Tab(text: i['label'])
], ],
begin: Alignment.topLeft, isScrollable: true,
end: Alignment.bottomRight, dividerColor: Colors.transparent,
stops: const [0, 0.0034, 0.34]), enableFeedback: true,
splashBorderRadius: BorderRadius.circular(10),
tabAlignment: TabAlignment.center,
onTap: (value) {
feedBack();
if (_homeController.initialIndex.value == value) {
_homeController.tabsCtrList[value]().animateToTop();
}
_homeController.initialIndex.value = value;
},
), ),
), ),
), ),
),
],
Column(
children: [
CustomAppBar(
stream: _homeController.hideSearchBar
? stream
: StreamController<bool>.broadcast().stream,
ctr: _homeController,
callback: showUserBottomSheet,
),
if (_homeController.tabs.length > 1) ...[
if (_homeController.enableGradientBg) ...[
const CustomTabs(),
] else ...[
const SizedBox(height: 4),
SizedBox(
width: double.infinity,
height: 42,
child: Align(
alignment: Alignment.center,
child: TabBar(
controller: _homeController.tabController,
tabs: [
for (var i in _homeController.tabs)
Tab(text: i['label'])
],
isScrollable: true,
dividerColor: Colors.transparent,
enableFeedback: true,
splashBorderRadius: BorderRadius.circular(10),
tabAlignment: TabAlignment.center,
onTap: (value) {
feedBack();
if (_homeController.initialIndex.value == value) {
_homeController.tabsCtrList[value]().animateToTop();
}
_homeController.initialIndex.value = value;
},
),
),
),
],
] else ...[
const SizedBox(height: 6),
],
Expanded(
child: TabBarView(
controller: _homeController.tabController,
children: _homeController.tabsPageList,
),
),
], ],
] else ...[
const SizedBox(height: 6),
],
Expanded(
child: TabBarView(
controller: _homeController.tabController,
children: _homeController.tabsPageList,
),
), ),
], ],
), ),
@ -280,7 +242,10 @@ class DefaultUser extends StatelessWidget {
style: ButtonStyle( style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero), padding: MaterialStateProperty.all(EdgeInsets.zero),
backgroundColor: MaterialStateProperty.resolveWith((states) { backgroundColor: MaterialStateProperty.resolveWith((states) {
return Theme.of(context).colorScheme.onInverseSurface; return Theme.of(context)
.colorScheme
.onSecondaryContainer
.withOpacity(0.05);
}), }),
), ),
onPressed: () => callback?.call(), onPressed: () => callback?.call(),
@ -317,7 +282,7 @@ class _CustomTabsState extends State<CustomTabs> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
height: 44, height: 44,
margin: const EdgeInsets.only(top: 4), margin: const EdgeInsets.only(top: 8),
child: Obx( child: Obx(
() => ListView.separated( () => ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 14.0), padding: const EdgeInsets.symmetric(horizontal: 14.0),

View File

@ -26,6 +26,7 @@ class MainController extends GetxController {
Box userInfoCache = GStrorage.userInfo; Box userInfoCache = GStrorage.userInfo;
RxBool userLogin = false.obs; RxBool userLogin = false.obs;
late Rx<DynamicBadgeMode> dynamicBadgeType = DynamicBadgeMode.number.obs; late Rx<DynamicBadgeMode> dynamicBadgeType = DynamicBadgeMode.number.obs;
late bool enableGradientBg;
@override @override
void onInit() { void onInit() {
@ -44,6 +45,8 @@ class MainController extends GetxController {
if (dynamicBadgeType.value != DynamicBadgeMode.hidden) { if (dynamicBadgeType.value != DynamicBadgeMode.hidden) {
getUnreadDynamic(); getUnreadDynamic();
} }
enableGradientBg =
setting.get(SettingBoxKey.enableGradientBg, defaultValue: true);
} }
void onBackPressed(BuildContext context) { void onBackPressed(BuildContext context) {

View File

@ -117,14 +117,47 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
}, },
child: Scaffold( child: Scaffold(
extendBody: true, extendBody: true,
body: PageView( body: Stack(
physics: const NeverScrollableScrollPhysics(), children: [
controller: _mainController.pageController, if (_mainController.enableGradientBg)
onPageChanged: (index) { Align(
_mainController.selectedIndex = index; alignment: Alignment.topLeft,
setState(() {}); child: Opacity(
}, opacity: 0.6,
children: _mainController.pages, child: Container(
width: MediaQuery.of(context).size.width,
// height: MediaQuery.of(context).size.height,
height: MediaQuery.of(context).padding.top + 400,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context)
.colorScheme
.primary
.withOpacity(0.6),
Theme.of(context)
.colorScheme
.surface
.withOpacity(0.3),
Theme.of(context).colorScheme.surface
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: const [0.1, 0.8, 1]),
),
),
),
),
PageView(
physics: const NeverScrollableScrollPhysics(),
controller: _mainController.pageController,
onPageChanged: (index) {
_mainController.selectedIndex = index;
setState(() {});
},
children: _mainController.pages,
),
],
), ),
bottomNavigationBar: _mainController.navigationBars.length > 1 bottomNavigationBar: _mainController.navigationBars.length > 1
? StreamBuilder( ? StreamBuilder(

View File

@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.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/models/user/fav_folder.dart'; import 'package:pilipala/models/user/fav_folder.dart';
import 'package:pilipala/pages/media/index.dart'; import 'package:pilipala/pages/media/index.dart';
import 'package:pilipala/utils/main_stream.dart';
import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/utils.dart';
class MediaPage extends StatefulWidget { class MediaPage extends StatefulWidget {
@ -46,7 +46,16 @@ class _MediaPageState extends State<MediaPage>
super.build(context); super.build(context);
Color primary = Theme.of(context).colorScheme.primary; Color primary = Theme.of(context).colorScheme.primary;
return Scaffold( return Scaffold(
appBar: AppBar(toolbarHeight: 30), backgroundColor: Colors.transparent,
appBar: AppBar(
elevation: 0,
scrolledUnderElevation: 0,
toolbarHeight: 30,
backgroundColor: Colors.transparent,
systemOverlayStyle: Theme.of(context).brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark,
),
body: SingleChildScrollView( body: SingleChildScrollView(
controller: mediaController.scrollController, controller: mediaController.scrollController,
child: Column( child: Column(

View File

@ -27,6 +27,7 @@ class MemberController extends GetxController {
RxString attributeText = '关注'.obs; RxString attributeText = '关注'.obs;
RxList<MemberCoinsDataModel> recentCoinsList = <MemberCoinsDataModel>[].obs; RxList<MemberCoinsDataModel> recentCoinsList = <MemberCoinsDataModel>[].obs;
RxList<MemberLikeDataModel> recentLikeList = <MemberLikeDataModel>[].obs; RxList<MemberLikeDataModel> recentLikeList = <MemberLikeDataModel>[].obs;
RxBool isOwner = false.obs;
@override @override
void onInit() { void onInit() {
@ -34,6 +35,7 @@ class MemberController extends GetxController {
mid = int.parse(Get.parameters['mid']!); mid = int.parse(Get.parameters['mid']!);
userInfo = userInfoCache.get('userInfoCache'); userInfo = userInfoCache.get('userInfoCache');
ownerMid = userInfo != null ? userInfo.mid : -1; ownerMid = userInfo != null ? userInfo.mid : -1;
isOwner.value = mid == ownerMid;
face.value = Get.arguments['face'] ?? ''; face.value = Get.arguments['face'] ?? '';
heroTag = Get.arguments['heroTag'] ?? ''; heroTag = Get.arguments['heroTag'] ?? '';
relationSearch(); relationSearch();
@ -197,11 +199,12 @@ class MemberController extends GetxController {
if (userInfo == null) return; if (userInfo == null) return;
var res = await MemberHttp.getMemberSeasons(mid, 1, 10); var res = await MemberHttp.getMemberSeasons(mid, 1, 10);
if (!res['status']) { if (!res['status']) {
SmartDialog.showToast("用户专栏请求异常:${res['msg']}"); SmartDialog.showToast("用户合集请求异常:${res['msg']}");
} else { } else {
// 只取前四个专栏 // 只取前四个专栏
res['data'].seasonsList.map((e) { res['data'].seasonsList.map((e) {
e.archives = e.archives!.sublist(0, 4); e.archives =
e.archives!.length > 4 ? e.archives!.sublist(0, 4) : e.archives!;
}).toList(); }).toList();
} }
return res; return res;
@ -235,4 +238,6 @@ class MemberController extends GetxController {
void pushRecentCoinsPage() async { void pushRecentCoinsPage() async {
if (recentCoinsList.isNotEmpty) {} if (recentCoinsList.isNotEmpty) {}
} }
void pushfavPage() => Get.toNamed('/fav?mid=$mid');
} }

View File

@ -159,29 +159,47 @@ class _MemberPageState extends State<MemberPage>
profileWidget(), profileWidget(),
/// 动态链接 /// 动态链接
ListTile( Obx(
onTap: _memberController.pushDynamicsPage, () => ListTile(
title: const Text('Ta的动态'), onTap: _memberController.pushDynamicsPage,
trailing: title: Text(
const Icon(Icons.arrow_forward_outlined, size: 19), '${_memberController.isOwner.value ? '' : 'Ta'}的动态'),
trailing:
const Icon(Icons.arrow_forward_outlined, size: 19),
),
), ),
const Divider(height: 1, thickness: 0.1), const Divider(height: 1, thickness: 0.1),
/// 视频 /// 视频
ListTile( Obx(() => ListTile(
onTap: _memberController.pushArchivesPage, onTap: _memberController.pushArchivesPage,
title: const Text('Ta的投稿'), title: Text(
trailing: '${_memberController.isOwner.value ? '' : 'Ta'}的投稿'),
const Icon(Icons.arrow_forward_outlined, size: 19), trailing: const Icon(Icons.arrow_forward_outlined,
), size: 19),
)),
const Divider(height: 1, thickness: 0.1),
/// 他的收藏夹
Obx(() => ListTile(
onTap: _memberController.pushfavPage,
title: Text(
'${_memberController.isOwner.value ? '' : 'Ta'}的收藏'),
trailing: const Icon(Icons.arrow_forward_outlined,
size: 19),
)),
const Divider(height: 1, thickness: 0.1), const Divider(height: 1, thickness: 0.1),
/// 专栏 /// 专栏
const ListTile(title: Text('Ta的专栏')), Obx(() => ListTile(
title: Text(
'${_memberController.isOwner.value ? '' : 'Ta'}的专栏'))),
const Divider(height: 1, thickness: 0.1), const Divider(height: 1, thickness: 0.1),
/// 合集 /// 合集
const ListTile(title: Text('Ta的合集')), Obx(() => ListTile(
title: Text(
'${_memberController.isOwner.value ? '' : 'Ta'}的合集'))),
MediaQuery.removePadding( MediaQuery.removePadding(
removeTop: true, removeTop: true,
removeBottom: true, removeBottom: true,
@ -212,8 +230,6 @@ class _MemberPageState extends State<MemberPage>
), ),
), ),
/// 收藏
/// 追番 /// 追番
/// 最近投币 /// 最近投币
Obx( Obx(

View File

@ -17,13 +17,10 @@ class RankController extends GetxController with GetTickerProviderStateMixin {
Box setting = GStrorage.setting; Box setting = GStrorage.setting;
late final StreamController<bool> searchBarStream = late final StreamController<bool> searchBarStream =
StreamController<bool>.broadcast(); StreamController<bool>.broadcast();
late bool enableGradientBg;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
enableGradientBg =
setting.get(SettingBoxKey.enableGradientBg, defaultValue: true);
// 进行tabs配置 // 进行tabs配置
setTabConfig(); setTabConfig();
} }

View File

@ -31,94 +31,56 @@ class _RankPageState extends State<RankPage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
Brightness currentBrightness = MediaQuery.of(context).platformBrightness;
// 设置状态栏图标的亮度
if (_rankController.enableGradientBg) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarIconBrightness: currentBrightness == Brightness.light
? Brightness.dark
: Brightness.light,
));
}
return Scaffold( return Scaffold(
extendBody: true, extendBody: true,
extendBodyBehindAppBar: false, extendBodyBehindAppBar: true,
appBar: _rankController.enableGradientBg backgroundColor: Colors.transparent,
? null appBar: AppBar(
: AppBar(toolbarHeight: 0, elevation: 0), toolbarHeight: 0,
body: Stack( elevation: 0,
backgroundColor: Colors.transparent,
systemOverlayStyle: Theme.of(context).brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark,
),
body: Column(
children: [ children: [
// gradient background const CustomAppBar(),
if (_rankController.enableGradientBg) ...[ if (_rankController.tabs.length > 1) ...[
Align( const SizedBox(height: 4),
alignment: Alignment.topLeft, SizedBox(
child: Opacity( width: double.infinity,
opacity: 0.6, height: 42,
child: Container( child: Align(
width: MediaQuery.of(context).size.width, alignment: Alignment.center,
height: MediaQuery.of(context).size.height, child: TabBar(
decoration: BoxDecoration( controller: _rankController.tabController,
gradient: LinearGradient( tabs: [
colors: [ for (var i in _rankController.tabs) Tab(text: i['label'])
Theme.of(context) ],
.colorScheme isScrollable: true,
.primary dividerColor: Colors.transparent,
.withOpacity(0.9), enableFeedback: true,
Theme.of(context) splashBorderRadius: BorderRadius.circular(10),
.colorScheme tabAlignment: TabAlignment.center,
.primary onTap: (value) {
.withOpacity(0.5), feedBack();
Theme.of(context).colorScheme.surface if (_rankController.initialIndex.value == value) {
], _rankController.tabsCtrList[value].animateToTop();
begin: Alignment.topLeft, }
end: Alignment.bottomRight, _rankController.initialIndex.value = value;
stops: const [0, 0.0034, 0.34]), },
),
), ),
), ),
), ),
] else ...[
const SizedBox(height: 6),
], ],
Column( Expanded(
children: [ child: TabBarView(
const CustomAppBar(), controller: _rankController.tabController,
if (_rankController.tabs.length > 1) ...[ children: _rankController.tabsPageList,
const SizedBox(height: 4), ),
SizedBox(
width: double.infinity,
height: 42,
child: Align(
alignment: Alignment.center,
child: TabBar(
controller: _rankController.tabController,
tabs: [
for (var i in _rankController.tabs)
Tab(text: i['label'])
],
isScrollable: true,
dividerColor: Colors.transparent,
enableFeedback: true,
splashBorderRadius: BorderRadius.circular(10),
tabAlignment: TabAlignment.center,
onTap: (value) {
feedBack();
if (_rankController.initialIndex.value == value) {
_rankController.tabsCtrList[value].animateToTop();
}
_rankController.initialIndex.value = value;
},
),
),
),
] else ...[
const SizedBox(height: 6),
],
Expanded(
child: TabBarView(
controller: _rankController.tabController,
children: _rankController.tabsPageList,
),
),
],
), ),
], ],
), ),

View File

@ -16,11 +16,17 @@ class SubController extends GetxController {
int currentPage = 1; int currentPage = 1;
int pageSize = 20; int pageSize = 20;
RxBool hasMore = true.obs; RxBool hasMore = true.obs;
late int mid;
late int ownerMid;
RxBool isOwner = false.obs;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
mid = int.parse(Get.parameters['mid'] ?? '-1');
userInfo = userInfoCache.get('userInfoCache'); userInfo = userInfoCache.get('userInfoCache');
ownerMid = userInfo != null ? userInfo!.mid! : -1;
isOwner.value = mid == -1 || mid == ownerMid;
} }
Future<dynamic> querySubFolder({type = 'init'}) async { Future<dynamic> querySubFolder({type = 'init'}) async {
@ -30,7 +36,7 @@ class SubController extends GetxController {
var res = await UserHttp.userSubFolder( var res = await UserHttp.userSubFolder(
pn: currentPage, pn: currentPage,
ps: pageSize, ps: pageSize,
mid: userInfo!.mid!, mid: isOwner.value ? ownerMid : mid,
); );
if (res['status']) { if (res['status']) {
if (type == 'init') { if (type == 'init') {

View File

@ -42,10 +42,10 @@ class _SubPageState extends State<SubPage> {
appBar: AppBar( appBar: AppBar(
centerTitle: false, centerTitle: false,
titleSpacing: 0, titleSpacing: 0,
title: Text( title: Obx(() => Text(
'的订阅', '${_subController.isOwner.value ? '' : 'Ta'}的订阅',
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), )),
), ),
body: FutureBuilder( body: FutureBuilder(
future: _futureBuilderFuture, future: _futureBuilderFuture,
@ -62,6 +62,7 @@ class _SubPageState extends State<SubPage> {
return SubItem( return SubItem(
subFolderItem: subFolderItem:
_subController.subFolderData.value.list![index], _subController.subFolderData.value.list![index],
isOwner: _subController.isOwner.value,
cancelSub: _subController.cancelSub); cancelSub: _subController.cancelSub);
}, },
), ),

View File

@ -8,10 +8,12 @@ import '../../../models/user/sub_folder.dart';
class SubItem extends StatelessWidget { class SubItem extends StatelessWidget {
final SubFolderItemData subFolderItem; final SubFolderItemData subFolderItem;
final bool isOwner;
final Function(SubFolderItemData) cancelSub; final Function(SubFolderItemData) cancelSub;
const SubItem({ const SubItem({
super.key, super.key,
required this.subFolderItem, required this.subFolderItem,
required this.isOwner,
required this.cancelSub, required this.cancelSub,
}); });
@ -59,6 +61,7 @@ class SubItem extends StatelessWidget {
), ),
VideoContent( VideoContent(
subFolderItem: subFolderItem, subFolderItem: subFolderItem,
isOwner: isOwner,
cancelSub: cancelSub, cancelSub: cancelSub,
) )
], ],
@ -73,8 +76,14 @@ class SubItem extends StatelessWidget {
class VideoContent extends StatelessWidget { class VideoContent extends StatelessWidget {
final SubFolderItemData subFolderItem; final SubFolderItemData subFolderItem;
final bool isOwner;
final Function(SubFolderItemData)? cancelSub; final Function(SubFolderItemData)? cancelSub;
const VideoContent({super.key, required this.subFolderItem, this.cancelSub}); const VideoContent({
super.key,
required this.subFolderItem,
required this.isOwner,
this.cancelSub,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -111,22 +120,24 @@ class VideoContent extends StatelessWidget {
), ),
), ),
const Spacer(), const Spacer(),
Row( isOwner
mainAxisAlignment: MainAxisAlignment.end, ? Row(
children: [ mainAxisAlignment: MainAxisAlignment.end,
IconButton( children: [
style: ButtonStyle( IconButton(
padding: MaterialStateProperty.all(EdgeInsets.zero), style: ButtonStyle(
), padding: MaterialStateProperty.all(EdgeInsets.zero),
onPressed: () => cancelSub?.call(subFolderItem), ),
icon: Icon( onPressed: () => cancelSub?.call(subFolderItem),
Icons.clear_outlined, icon: Icon(
color: Theme.of(context).colorScheme.outline, Icons.clear_outlined,
size: 18, color: Theme.of(context).colorScheme.outline,
), size: 18,
) ),
], )
) ],
)
: const SizedBox()
], ],
), ),
), ),

View File

@ -4,6 +4,7 @@ import 'dart:ui';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
import 'package:floating/floating.dart'; import 'package:floating/floating.dart';
import 'package:flutter/services.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';