improve ui

This commit is contained in:
nyne
2024-10-26 19:39:12 +08:00
parent e64b69d818
commit 96bf3688d0
12 changed files with 112 additions and 84 deletions

View File

@@ -73,8 +73,12 @@ class _AppbarState extends State<Appbar> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var content = SizedBox( var content = Container(
height: _kAppBarHeight, decoration: BoxDecoration(
color: widget.backgroundColor ??
context.colorScheme.surface.withOpacity(0.72),
),
height: _kAppBarHeight + context.padding.top,
child: Row( child: Row(
children: [ children: [
const SizedBox(width: 8), const SizedBox(width: 8),
@@ -102,17 +106,12 @@ class _AppbarState extends State<Appbar> {
width: 8, width: 8,
) )
], ],
), ).paddingTop(context.padding.top),
).paddingTop(context.padding.top); );
if (widget.backgroundColor != Colors.transparent) { return BlurEffect(
return Material( blur: _scrolledUnder ? 15 : 0,
elevation: (_scrolledUnder && context.width < changePoint) ? 1 : 0, child: content,
surfaceTintColor: Theme.of(context).colorScheme.surfaceTint, );
color: widget.backgroundColor ?? Theme.of(context).colorScheme.surface,
child: content,
);
}
return content;
} }
} }
@@ -192,7 +191,7 @@ class _MySliverAppBarDelegate extends SliverPersistentHeaderDelegate {
) )
: const SizedBox()), : const SizedBox()),
const SizedBox( const SizedBox(
width: 24, width: 16,
), ),
Expanded( Expanded(
child: DefaultTextStyle( child: DefaultTextStyle(

View File

@@ -735,6 +735,12 @@ class ComicListState extends State<ComicList> {
} }
Future<void> _loadPage(int page) async { Future<void> _loadPage(int page) async {
if (widget.loadPage == null && widget.loadNext == null) {
_error = "loadPage and loadNext can't be null at the same time";
Future.microtask(() {
setState(() {});
});
}
if (_loading[page] == true) { if (_loading[page] == true) {
return; return;
} }
@@ -790,9 +796,6 @@ class ComicListState extends State<ComicList> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (widget.loadPage == null && widget.loadNext == null) {
throw Exception("loadPage and loadNext can't be null at the same time");
}
if (_error != null) { if (_error != null) {
return Column( return Column(
children: [ children: [
@@ -814,19 +817,27 @@ class ComicListState extends State<ComicList> {
} }
if (_data[_page] == null) { if (_data[_page] == null) {
_loadPage(_page); _loadPage(_page);
return const Center( return Column(
child: CircularProgressIndicator(), children: [
if (widget.errorLeading != null) widget.errorLeading!,
const Expanded(
child: Center(
child: CircularProgressIndicator(),
),
),
],
); );
} }
return SmoothCustomScrollView( return SmoothCustomScrollView(
slivers: [ slivers: [
if (widget.leadingSliver != null) widget.leadingSliver!, if (widget.leadingSliver != null) widget.leadingSliver!,
_buildSliverPageSelector(), if (_maxPage != 1) _buildSliverPageSelector(),
SliverGridComics( SliverGridComics(
comics: _data[_page] ?? const [], comics: _data[_page] ?? const [],
menuBuilder: widget.menuBuilder, menuBuilder: widget.menuBuilder,
), ),
if (_data[_page]!.length > 6) _buildSliverPageSelector(), if (_data[_page]!.length > 6 && _maxPage != 1)
_buildSliverPageSelector(),
if (widget.trailingSliver != null) widget.trailingSliver!, if (widget.trailingSliver != null) widget.trailingSliver!,
], ],
); );

View File

@@ -148,7 +148,7 @@ class _NaviPaneState extends State<NaviPane>
return _NaviPopScope( return _NaviPopScope(
action: () { action: () {
if (App.mainNavigatorKey!.currentState!.canPop()) { if (App.mainNavigatorKey!.currentState!.canPop()) {
App.mainNavigatorKey!.currentState!.pop(); App.mainNavigatorKey!.currentState!.maybePop();
} else { } else {
SystemNavigator.pop(); SystemNavigator.pop();
} }
@@ -627,16 +627,9 @@ class _NaviPopScope extends StatelessWidget {
? child ? child
: PopScope( : PopScope(
canPop: App.isAndroid ? false : true, canPop: App.isAndroid ? false : true,
// flutter <3.24.0 api
onPopInvoked: (value) {
action();
},
/*
flutter >=3.24.0 api
onPopInvokedWithResult: (value, result) { onPopInvokedWithResult: (value, result) {
action(); action();
}, },
*/
child: child, child: child,
); );
if (popGesture) { if (popGesture) {

View File

@@ -116,6 +116,7 @@ mixin _AppRouteTransitionMixin<T> on PageRoute<T> {
route.fullscreenDialog || route.fullscreenDialog ||
route.animation!.status != AnimationStatus.completed || route.animation!.status != AnimationStatus.completed ||
route.secondaryAnimation!.status != AnimationStatus.dismissed || route.secondaryAnimation!.status != AnimationStatus.dismissed ||
!route.popGestureEnabled ||
route.navigator!.userGestureInProgress) { route.navigator!.userGestureInProgress) {
return false; return false;
} }

View File

@@ -728,28 +728,32 @@ class ComicSourceParser {
return retryZone(func); return retryZone(func);
}; };
addFolder = (name) async { if(_checkExists("favorites.addFolder")) {
try { addFolder = (name) async {
await JsEngine().runCode(""" try {
await JsEngine().runCode("""
ComicSource.sources.$_key.favorites.addFolder(${jsonEncode(name)}) ComicSource.sources.$_key.favorites.addFolder(${jsonEncode(name)})
"""); """);
return const Res(true); return const Res(true);
} catch (e, s) { } catch (e, s) {
Log.error("Network", "$e\n$s"); Log.error("Network", "$e\n$s");
return Res.error(e.toString()); return Res.error(e.toString());
} }
}; };
deleteFolder = (key) async { }
try { if(_checkExists("favorites.deleteFolder")) {
await JsEngine().runCode(""" deleteFolder = (key) async {
try {
await JsEngine().runCode("""
ComicSource.sources.$_key.favorites.deleteFolder(${jsonEncode(key)}) ComicSource.sources.$_key.favorites.deleteFolder(${jsonEncode(key)})
"""); """);
return const Res(true); return const Res(true);
} catch (e, s) { } catch (e, s) {
Log.error("Network", "$e\n$s"); Log.error("Network", "$e\n$s");
return Res.error(e.toString()); return Res.error(e.toString());
} }
}; };
}
} }
return FavoriteData( return FavoriteData(

View File

@@ -153,6 +153,8 @@ class HistoryManager with ChangeNotifier {
Map<String, bool>? _cachedHistory; Map<String, bool>? _cachedHistory;
static const _kMaxHistoryLength = 200;
Future<void> init() async { Future<void> init() async {
_db = sqlite3.open("${App.dataPath}/history.db"); _db = sqlite3.open("${App.dataPath}/history.db");
@@ -176,6 +178,12 @@ class HistoryManager with ChangeNotifier {
/// ///
/// This function would be called when user start reading. /// This function would be called when user start reading.
Future<void> addHistory(History newItem) async { Future<void> addHistory(History newItem) async {
while(count() >= _kMaxHistoryLength) {
_db.execute("""
delete from history
where time == (select min(time) from history);
""");
}
_db.execute(""" _db.execute("""
insert or replace into history (id, title, subtitle, cover, time, type, ep, page, readEpisode, max_page) insert or replace into history (id, title, subtitle, cover, time, type, ep, page, readEpisode, max_page)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?); values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
@@ -207,6 +215,7 @@ class HistoryManager with ChangeNotifier {
where id == ? and type == ?; where id == ? and type == ?;
""", [id, type.value]); """, [id, type.value]);
updateCache(); updateCache();
notifyListeners();
} }
Future<History?> find(String id, ComicType type) async { Future<History?> find(String id, ComicType type) async {

View File

@@ -56,13 +56,16 @@ class _CategoryComicsPageState extends State<CategoryComicsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var topPadding = context.padding.top + 56.0;
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true,
appBar: Appbar( appBar: Appbar(
title: Text(widget.category), title: Text(widget.category),
), ),
body: ComicList( body: ComicList(
key: Key(widget.category + optionsValue.toString()), key: Key(widget.category + optionsValue.toString()),
leadingSliver: buildOptions().toSliver(), errorLeading: SizedBox(height: topPadding),
leadingSliver: buildOptions().paddingTop(topPadding).toSliver(),
loadPage: (i) => data.load( loadPage: (i) => data.load(
widget.category, widget.category,
widget.param, widget.param,

View File

@@ -92,6 +92,9 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
@override @override
Future<Res<ComicDetails>> loadData() async { Future<Res<ComicDetails>> loadData() async {
var comicSource = ComicSource.find(widget.sourceKey); var comicSource = ComicSource.find(widget.sourceKey);
if(comicSource == null) {
return const Res.error('Comic source not found');
}
isAddToLocalFav = LocalFavoritesManager().isExist( isAddToLocalFav = LocalFavoritesManager().isExist(
widget.id, widget.id,
ComicType(widget.sourceKey.hashCode), ComicType(widget.sourceKey.hashCode),

View File

@@ -206,6 +206,7 @@ class _BodyState extends State<_Body> {
source.data['settings'][key] ?? item.value['default'] ?? ''; source.data['settings'][key] ?? item.value['default'] ?? '';
yield ListTile( yield ListTile(
title: Text((item.value['title'] as String).ts(source.key)), title: Text((item.value['title'] as String).ts(source.key)),
subtitle: Text(current, maxLines: 1, overflow: TextOverflow.ellipsis),
trailing: IconButton( trailing: IconButton(
icon: const Icon(Icons.edit), icon: const Icon(Icons.edit),
onPressed: () { onPressed: () {

View File

@@ -71,11 +71,16 @@ class NetworkFavoritePage extends StatelessWidget {
} }
} }
class _NormalFavoritePage extends StatelessWidget { class _NormalFavoritePage extends StatefulWidget {
_NormalFavoritePage(this.data); const _NormalFavoritePage(this.data);
final FavoriteData data; final FavoriteData data;
@override
State<_NormalFavoritePage> createState() => _NormalFavoritePageState();
}
class _NormalFavoritePageState extends State<_NormalFavoritePage> {
final comicListKey = GlobalKey<ComicListState>(); final comicListKey = GlobalKey<ComicListState>();
@override @override
@@ -95,7 +100,7 @@ class _NormalFavoritePage extends StatelessWidget {
) )
: null, : null,
), ),
title: Text(data.title), title: Text(widget.data.title),
), ),
errorLeading: Appbar( errorLeading: Appbar(
leading: Tooltip( leading: Tooltip(
@@ -110,10 +115,10 @@ class _NormalFavoritePage extends StatelessWidget {
) )
: null, : null,
), ),
title: Text(data.title), title: Text(widget.data.title),
), ),
loadPage: data.loadComic == null ? null : (i) => data.loadComic!(i), loadPage: widget.data.loadComic == null ? null : (i) => widget.data.loadComic!(i),
loadNext: data.loadNext == null ? null : (next) => data.loadNext!(next), loadNext: widget.data.loadNext == null ? null : (next) => widget.data.loadNext!(next),
menuBuilder: (comic) { menuBuilder: (comic) {
return [ return [
MenuEntry( MenuEntry(
@@ -280,7 +285,7 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> {
} }
}), }),
maxCrossAxisExtent: 450, maxCrossAxisExtent: 450,
itemHeight: 64, itemHeight: 52,
), ),
if (widget.data.addFolder != null) if (widget.data.addFolder != null)
SliverToBoxAdapter( SliverToBoxAdapter(
@@ -342,17 +347,13 @@ class _FolderTile extends StatelessWidget {
return Material( return Material(
child: InkWell( child: InkWell(
onTap: onTap, onTap: onTap,
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Padding( child: Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 16, 8), padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
child: Row( child: Row(
children: [ children: [
const SizedBox(
width: 16,
),
Icon( Icon(
Icons.folder, Icons.folder,
size: 35, size: 28,
color: Theme.of(context).colorScheme.secondary, color: Theme.of(context).colorScheme.secondary,
), ),
const SizedBox( const SizedBox(
@@ -370,15 +371,11 @@ class _FolderTile extends StatelessWidget {
), ),
if (deleteFolder != null) if (deleteFolder != null)
IconButton( IconButton(
icon: const Icon(Icons.delete_forever_outlined), icon: const Icon(Icons.delete_outline),
onPressed: () => onDeleteFolder(context), onPressed: () => onDeleteFolder(context),
) )
else else
const Icon(Icons.arrow_right), const Icon(Icons.arrow_right),
if (deleteFolder == null)
const SizedBox(
width: 8,
)
], ],
), ),
), ),

View File

@@ -85,7 +85,7 @@ class _HistoryPageState extends State<HistoryPage> {
e.subtitle, e.subtitle,
null, null,
getDescription(e), getDescription(e),
e.type.comicSource?.key ?? "Invalid", e.type.comicSource?.key ?? "Invalid:${e.type.value}",
null, null,
null, null,
); );
@@ -100,10 +100,17 @@ class _HistoryPageState extends State<HistoryPage> {
icon: Icons.remove, icon: Icons.remove,
text: 'Remove'.tl, text: 'Remove'.tl,
onClick: () { onClick: () {
HistoryManager().remove( if(c.sourceKey.startsWith("Invalid")) {
c.id, HistoryManager().remove(
ComicType(c.sourceKey.hashCode), c.id,
); ComicType(int.parse(c.sourceKey.split(':')[1])),
);
} else {
HistoryManager().remove(
c.id,
ComicType(c.sourceKey.hashCode),
);
}
}, },
), ),
]; ];

View File

@@ -38,23 +38,23 @@ class _RankingPageState extends State<RankingPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var topPadding = context.padding.top + 56;
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true,
appBar: Appbar( appBar: Appbar(
title: Text("Ranking".tl), title: Text("Ranking".tl),
), ),
body: Column( body: ComicList(
children: [ key: Key(optionValue),
Expanded( errorLeading: SizedBox(height: topPadding),
child: ComicList( leadingSliver:
loadPage: data.rankingData!.load == null buildOptions().sliverPadding(EdgeInsets.only(top: topPadding)),
? null loadPage: data.rankingData!.load == null
: (i) => data.rankingData!.load!(optionValue, i), ? null
loadNext: data.rankingData!.loadWithNext == null : (i) => data.rankingData!.load!(optionValue, i),
? null loadNext: data.rankingData!.loadWithNext == null
: (i) => data.rankingData!.loadWithNext!(optionValue, i), ? null
), : (i) => data.rankingData!.loadWithNext!(optionValue, i),
),
],
), ),
); );
} }