Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ android {

signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
keyAlias = keystoreProperties["keyAlias"]?.toString()
keyPassword = keystoreProperties["keyPassword"]?.toString()
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
storePassword = keystoreProperties["storePassword"] as String
storePassword = keystoreProperties["storePassword"]?.toString()
}
}

Expand Down
75 changes: 75 additions & 0 deletions lib/component/illust_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ class _IllustCardState extends State<IllustCard> {
child: Stack(
children: [
Positioned.fill(child: _buildPic(tag, tooLong)),
Positioned(
top: 5.0,
left: 5.0,
child: _buildR18Badge(),
),
Positioned(
top: 5.0,
right: 5.0,
Expand All @@ -204,6 +209,11 @@ class _IllustCardState extends State<IllustCard> {
_buildVisibility()
],
)),
Positioned(
bottom: 5.0,
left: 5.0,
child: _buildStatsBadge(),
),
// Positioned(
// top: 0,
// left: 0,
Expand Down Expand Up @@ -243,6 +253,46 @@ class _IllustCardState extends State<IllustCard> {
));
}

Widget _buildStatsBadge() {
return Container(
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 4.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.visibility, color: Colors.white, size: 12),
SizedBox(width: 2),
Text(
"${_abbreviateNumber(store.illusts!.totalView)}",
style: TextStyle(color: Colors.white, fontSize: 12),
),
SizedBox(width: 4),
Icon(Icons.bookmark, color: Colors.white, size: 12),
SizedBox(width: 2),
Text(
"${_abbreviateNumber(store.illusts!.totalBookmarks)}",
style: TextStyle(color: Colors.white, fontSize: 12),
),
],
),
),
);
}

String _abbreviateNumber(int number) {
if (number >= 1000000) {
return '${(number / 1000000).toStringAsFixed(1)}M';
} else if (number >= 1000) {
return '${(number / 1000).toStringAsFixed(1)}K';
} else {
return number.toString();
}
}

Widget _buildAIBadge() {
return Container(
decoration: BoxDecoration(
Expand All @@ -259,6 +309,31 @@ class _IllustCardState extends State<IllustCard> {
);
}

Widget _buildR18Badge() {
String text = "";
if (store.illusts!.xRestrict == 2) {
text = "R-18G";
} else if (store.illusts!.xRestrict == 1) {
text = "R-18";
}

if (text.isEmpty) return Container();

return Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 4.0),
child: Text(
text,
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
);
}

Widget _buildAnimationWraper(BuildContext context, Widget child) {
return InkWell(
onLongPress: () {
Expand Down
136 changes: 136 additions & 0 deletions lib/component/multi_function_fab.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright (C) 2020. by perol_notsf, All rights reserved
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import 'package:flutter/material.dart';
import 'package:pixez/main.dart';
import 'package:pixez/page/novel/novel_rail.dart';

class MultiFunctionFab extends StatefulWidget {
final VoidCallback onRefresh;

const MultiFunctionFab({Key? key, required this.onRefresh}) : super(key: key);

@override
_MultiFunctionFabState createState() => _MultiFunctionFabState();
}

class _MultiFunctionFabState extends State<MultiFunctionFab>
with SingleTickerProviderStateMixin {
bool _isExpanded = false;
late AnimationController _animationController;
late Animation<Offset> _slideAnimation;

@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: Duration(milliseconds: 150),
vsync: this,
);
_slideAnimation = Tween<Offset>(
begin: Offset(0, 1),
end: Offset(0, 0),
).animate(CurvedAnimation(
parent: _animationController,
curve: Curves.linear,
));
}

@override
void dispose() {
_animationController.dispose();
super.dispose();
}

void _toggleExpanded() {
setState(() {
_isExpanded = !_isExpanded;
if (_isExpanded) {
_animationController.forward();
} else {
_animationController.reverse();
}
});
}

@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// 跳转到小说首页按钮
if (_isExpanded)
SlideTransition(
position: _slideAnimation,
child: Container(
margin: EdgeInsets.only(bottom: 16),
child: FloatingActionButton(
heroTag: "fab_novel",
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => NovelRail()));
_toggleExpanded();
},
child: Icon(Icons.book),
mini: true,
),
),
),
// 回到顶部按钮
if (_isExpanded)
SlideTransition(
position: _slideAnimation,
child: Container(
margin: EdgeInsets.only(bottom: 16),
child: FloatingActionButton(
heroTag: "fab_top",
onPressed: () {
// 发送回到顶部信号
topStore.setTop("100");
_toggleExpanded();
},
child: Icon(Icons.arrow_upward),
mini: true,
),
),
),
// 刷新按钮
if (_isExpanded)
SlideTransition(
position: _slideAnimation,
child: Container(
margin: EdgeInsets.only(bottom: 16),
child: FloatingActionButton(
heroTag: "fab_refresh",
onPressed: () {
widget.onRefresh();
_toggleExpanded();
},
child: Icon(Icons.refresh),
mini: true,
),
),
),
// 主按钮
FloatingActionButton(
heroTag: "fab_main",
onPressed: _toggleExpanded,
child: Icon(_isExpanded ? Icons.close : Icons.menu),
),
],
);
}
}
54 changes: 40 additions & 14 deletions lib/page/hello/android_hello_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:pixez/component/painter_avatar.dart';
import 'package:pixez/component/multi_function_fab.dart';
import 'package:pixez/constants.dart';
import 'package:pixez/deep_link_plugin.dart';
import 'package:pixez/er/leader.dart';
Expand Down Expand Up @@ -59,6 +60,11 @@ class _AndroidHelloPageState extends State<AndroidHelloPage> {
fullScreenStore.toggle();
}

void _refreshCurrentPage() {
// 发送刷新信号"101",专门用于触发刷新操作
topStore.setTop("101");
}

@override
Widget build(BuildContext context) {
return Observer(builder: (context) {
Expand Down Expand Up @@ -128,20 +134,40 @@ class _AndroidHelloPageState extends State<AndroidHelloPage> {
}

Widget _buildPageView(BuildContext context) {
return Stack(
children: [
_buildPageContent(context),
Positioned(
bottom: MediaQuery.of(context).padding.bottom + 16,
right: 16,
child: Observer(builder: (context) {
return AnimatedToggleFullscreenFAB(
isFullscreen: fullScreenStore.fullscreen,
toggleFullscreen: toggleFullscreen);
}),
)
],
);
return LayoutBuilder(builder: (context, constraints) {
final wide = constraints.maxWidth > constraints.maxHeight;
return Stack(
children: [
_buildPageContent(context),
Positioned(
bottom: wide
? 16 // 横屏时使用较小的底部边距
: MediaQuery.of(context).padding.bottom + 16, // 竖屏时避免被导航栏遮挡
right: 16,
child: Observer(builder: (context) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// 只在首页显示多功能按钮
if (index == 0)
MultiFunctionFab(
onRefresh: _refreshCurrentPage,
),
// 当同时显示多功能按钮和全屏按钮时添加间距
if (index == 0 && fullScreenStore.fullscreen)
SizedBox(height: 8),
// 显示全屏切换按钮
AnimatedToggleFullscreenFAB(
isFullscreen: fullScreenStore.fullscreen,
toggleFullscreen: toggleFullscreen,
),
],
);
}),
)
],
);
});
}

Widget _buildNavigationBar(BuildContext context) {
Expand Down
28 changes: 27 additions & 1 deletion lib/page/hello/recom/recom_spotlight_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,35 @@ class _RecomSpolightPageState extends State<RecomSpolightPage>
)..easyRefreshController = _easyRefreshController;
super.initState();
subscription = topStore.topStream.listen((event) {
// 处理返回顶部信号
if (event == "100") {
_scrollController.position.jumpTo(0);
_scrollToTop();
}
// 处理刷新信号
else if (event == "101") {
_triggerRefreshAnimation();
}
});
}

/// 滚动到页面顶部
void _scrollToTop() {
if (_scrollController.hasClients) {
_scrollController.position.jumpTo(0);
}
}

/// 触发刷新动画和操作
void _triggerRefreshAnimation() {
// 先滚动到顶部,然后延迟触发刷新动画,确保动画能完整显示
_scrollToTop();

// 使用addPostFrameCallback确保滚动完成后才触发刷新
WidgetsBinding.instance.addPostFrameCallback((_) {
// 添加一个小延迟确保滚动完成
Future.delayed(Duration(milliseconds: 100), () {
_easyRefreshController.callRefresh();
});
});
}

Expand Down
Loading