mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
Add AppbarStyle.shadow;
Improve favorites page ui.
This commit is contained in:
@@ -115,6 +115,11 @@ class _AppbarState extends State<Appbar> {
|
||||
}
|
||||
}
|
||||
|
||||
enum AppbarStyle {
|
||||
blur,
|
||||
shadow,
|
||||
}
|
||||
|
||||
class SliverAppbar extends StatelessWidget {
|
||||
const SliverAppbar({
|
||||
super.key,
|
||||
@@ -122,6 +127,7 @@ class SliverAppbar extends StatelessWidget {
|
||||
this.leading,
|
||||
this.actions,
|
||||
this.radius = 0,
|
||||
this.style = AppbarStyle.blur,
|
||||
});
|
||||
|
||||
final Widget? leading;
|
||||
@@ -132,6 +138,8 @@ class SliverAppbar extends StatelessWidget {
|
||||
|
||||
final double radius;
|
||||
|
||||
final AppbarStyle style;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SliverPersistentHeader(
|
||||
@@ -142,6 +150,7 @@ class SliverAppbar extends StatelessWidget {
|
||||
actions: actions,
|
||||
topPadding: MediaQuery.of(context).padding.top,
|
||||
radius: radius,
|
||||
style: style,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -160,57 +169,74 @@ class _MySliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
||||
|
||||
final double radius;
|
||||
|
||||
_MySliverAppBarDelegate(
|
||||
{this.leading,
|
||||
required this.title,
|
||||
this.actions,
|
||||
required this.topPadding,
|
||||
this.radius = 0});
|
||||
final AppbarStyle style;
|
||||
|
||||
_MySliverAppBarDelegate({
|
||||
this.leading,
|
||||
required this.title,
|
||||
this.actions,
|
||||
required this.topPadding,
|
||||
this.radius = 0,
|
||||
this.style = AppbarStyle.blur,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(
|
||||
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
||||
return SizedBox.expand(
|
||||
child: BlurEffect(
|
||||
blur: 15,
|
||||
child: Material(
|
||||
color: context.colorScheme.surface.withOpacity(0.72),
|
||||
elevation: 0,
|
||||
borderRadius: BorderRadius.circular(radius),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(width: 8),
|
||||
leading ??
|
||||
(Navigator.of(context).canPop()
|
||||
? Tooltip(
|
||||
message: "Back".tl,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.maybePop(context),
|
||||
),
|
||||
)
|
||||
: const SizedBox()),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
var body = Row(
|
||||
children: [
|
||||
const SizedBox(width: 8),
|
||||
leading ??
|
||||
(Navigator.of(context).canPop()
|
||||
? Tooltip(
|
||||
message: "Back".tl,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.maybePop(context),
|
||||
),
|
||||
Expanded(
|
||||
child: DefaultTextStyle(
|
||||
style:
|
||||
DefaultTextStyle.of(context).style.copyWith(fontSize: 20),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
child: title,
|
||||
),
|
||||
),
|
||||
...?actions,
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
)
|
||||
],
|
||||
).paddingTop(topPadding),
|
||||
)
|
||||
: const SizedBox()),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
),
|
||||
);
|
||||
Expanded(
|
||||
child: DefaultTextStyle(
|
||||
style:
|
||||
DefaultTextStyle.of(context).style.copyWith(fontSize: 20),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
child: title,
|
||||
),
|
||||
),
|
||||
...?actions,
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
)
|
||||
],
|
||||
).paddingTop(topPadding);
|
||||
|
||||
if(style == AppbarStyle.blur) {
|
||||
return SizedBox.expand(
|
||||
child: BlurEffect(
|
||||
blur: 15,
|
||||
child: Material(
|
||||
color: context.colorScheme.surface.withOpacity(0.72),
|
||||
elevation: 0,
|
||||
borderRadius: BorderRadius.circular(radius),
|
||||
child: body,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SizedBox.expand(
|
||||
child: Material(
|
||||
color: context.colorScheme.surface,
|
||||
elevation: shrinkOffset == 0 ? 0 : 2,
|
||||
borderRadius: BorderRadius.circular(radius),
|
||||
child: body,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -224,7 +250,10 @@ class _MySliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
||||
return oldDelegate is! _MySliverAppBarDelegate ||
|
||||
leading != oldDelegate.leading ||
|
||||
title != oldDelegate.title ||
|
||||
actions != oldDelegate.actions;
|
||||
actions != oldDelegate.actions ||
|
||||
topPadding != oldDelegate.topPadding ||
|
||||
radius != oldDelegate.radius ||
|
||||
style != oldDelegate.style;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -778,7 +778,7 @@ class _SliverGridComics extends StatelessWidget {
|
||||
duration: const Duration(milliseconds: 150),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
? Theme.of(context).colorScheme.secondaryContainer.withOpacity(0.72)
|
||||
: null,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
|
@@ -9,6 +9,7 @@ import 'package:venera/foundation/app.dart';
|
||||
import 'package:venera/foundation/appdata.dart';
|
||||
import 'package:venera/foundation/comic_source/comic_source.dart';
|
||||
import 'package:venera/foundation/comic_type.dart';
|
||||
import 'package:venera/foundation/consts.dart';
|
||||
import 'package:venera/foundation/favorites.dart';
|
||||
import 'package:venera/foundation/local.dart';
|
||||
import 'package:venera/foundation/res.dart';
|
||||
|
@@ -74,6 +74,9 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
body: SmoothCustomScrollView(slivers: [
|
||||
if (!searchMode && !multiSelectMode)
|
||||
SliverAppbar(
|
||||
style: context.width < changePoint
|
||||
? AppbarStyle.shadow
|
||||
: AppbarStyle.blur,
|
||||
leading: Tooltip(
|
||||
message: "Folders".tl,
|
||||
child: context.width <= _kTwoPanelChangeWidth
|
||||
@@ -225,8 +228,7 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
showConfirmDialog(
|
||||
context: App.rootContext,
|
||||
title: "Delete".tl,
|
||||
content:
|
||||
"Delete folder '@f' ?".tlParams({
|
||||
content: "Delete folder '@f' ?".tlParams({
|
||||
"f": widget.folder,
|
||||
}),
|
||||
btnColor: context.colorScheme.error,
|
||||
@@ -243,6 +245,9 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
)
|
||||
else if (multiSelectMode)
|
||||
SliverAppbar(
|
||||
style: context.width < changePoint
|
||||
? AppbarStyle.shadow
|
||||
: AppbarStyle.blur,
|
||||
leading: Tooltip(
|
||||
message: "Cancel".tl,
|
||||
child: IconButton(
|
||||
@@ -287,8 +292,8 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
showConfirmDialog(
|
||||
context: context,
|
||||
title: "Delete".tl,
|
||||
content:
|
||||
"Delete @c comics?".tlParams({"c": selectedComics.length}),
|
||||
content: "Delete @c comics?"
|
||||
.tlParams({"c": selectedComics.length}),
|
||||
btnColor: context.colorScheme.error,
|
||||
onConfirm: () {
|
||||
_deleteComicWithId();
|
||||
@@ -300,6 +305,9 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
)
|
||||
else if (searchMode)
|
||||
SliverAppbar(
|
||||
style: context.width < changePoint
|
||||
? AppbarStyle.shadow
|
||||
: AppbarStyle.blur,
|
||||
leading: Tooltip(
|
||||
message: "Cancel".tl,
|
||||
child: IconButton(
|
||||
@@ -407,159 +415,134 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
.where((folder) => folder != favPage.folder)
|
||||
.toList();
|
||||
|
||||
showDialog(
|
||||
context: App.rootContext,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 50),
|
||||
child: Container(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 700, maxWidth: 500),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
favPage.folder ?? "Unselected".tl,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
showPopUpWidget(
|
||||
App.rootContext,
|
||||
StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return PopUpWidgetScaffold(
|
||||
title: favPage.folder ?? "Unselected".tl,
|
||||
body: Padding(
|
||||
padding: EdgeInsets.only(bottom: context.padding.bottom + 16),
|
||||
child: Container(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 700, maxWidth: 500),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: targetFolders.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == targetFolders.length) {
|
||||
return SizedBox(
|
||||
height: 36,
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
newFolder().then((v) {
|
||||
setState(() {
|
||||
targetFolders = LocalFavoritesManager()
|
||||
.folderNames
|
||||
.where((folder) =>
|
||||
folder != favPage.folder)
|
||||
.toList();
|
||||
});
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.add, size: 20),
|
||||
const SizedBox(width: 4),
|
||||
Text("New Folder".tl),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
var folder = targetFolders[index];
|
||||
var disabled = false;
|
||||
if (selectedLocalFolders.isNotEmpty) {
|
||||
if (added.contains(folder) &&
|
||||
!added.contains(selectedLocalFolders.first)) {
|
||||
disabled = true;
|
||||
} else if (!added.contains(folder) &&
|
||||
added.contains(selectedLocalFolders.first)) {
|
||||
disabled = true;
|
||||
}
|
||||
}
|
||||
return CheckboxListTile(
|
||||
title: Row(
|
||||
children: [
|
||||
Text(folder),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: targetFolders.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == targetFolders.length) {
|
||||
return SizedBox(
|
||||
height: 36,
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
newFolder().then((v) {
|
||||
setState(() {
|
||||
targetFolders =
|
||||
LocalFavoritesManager()
|
||||
.folderNames
|
||||
.where((folder) =>
|
||||
folder !=
|
||||
favPage.folder)
|
||||
.toList();
|
||||
});
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.add, size: 20),
|
||||
const SizedBox(width: 4),
|
||||
Text("New Folder".tl),
|
||||
],
|
||||
),
|
||||
),
|
||||
value: selectedLocalFolders.contains(folder),
|
||||
onChanged: disabled
|
||||
? null
|
||||
: (v) {
|
||||
setState(() {
|
||||
if (v!) {
|
||||
selectedLocalFolders.add(folder);
|
||||
} else {
|
||||
selectedLocalFolders.remove(folder);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: FilledButton(
|
||||
onPressed: () {
|
||||
if (selectedLocalFolders.isEmpty) {
|
||||
return;
|
||||
}
|
||||
if (option == 'move') {
|
||||
for (var c in selectedComics.keys) {
|
||||
for (var s in selectedLocalFolders) {
|
||||
LocalFavoritesManager().moveFavorite(
|
||||
favPage.folder as String,
|
||||
s,
|
||||
c.id,
|
||||
(c as FavoriteItem).type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var c in selectedComics.keys) {
|
||||
for (var s in selectedLocalFolders) {
|
||||
LocalFavoritesManager().addComic(
|
||||
s,
|
||||
FavoriteItem(
|
||||
id: c.id,
|
||||
name: c.title,
|
||||
coverPath: c.cover,
|
||||
author: c.subtitle ?? '',
|
||||
type: ComicType((c.sourceKey == 'local'
|
||||
? 0
|
||||
: c.sourceKey.hashCode)),
|
||||
tags: c.tags ?? [],
|
||||
),
|
||||
);
|
||||
}
|
||||
var folder = targetFolders[index];
|
||||
var disabled = false;
|
||||
if (selectedLocalFolders.isNotEmpty) {
|
||||
if (added.contains(folder) &&
|
||||
!added
|
||||
.contains(selectedLocalFolders.first)) {
|
||||
disabled = true;
|
||||
} else if (!added.contains(folder) &&
|
||||
added
|
||||
.contains(selectedLocalFolders.first)) {
|
||||
disabled = true;
|
||||
}
|
||||
}
|
||||
return CheckboxListTile(
|
||||
title: Row(
|
||||
children: [
|
||||
Text(folder),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
),
|
||||
value: selectedLocalFolders.contains(folder),
|
||||
onChanged: disabled
|
||||
? null
|
||||
: (v) {
|
||||
setState(() {
|
||||
if (v!) {
|
||||
selectedLocalFolders.add(folder);
|
||||
} else {
|
||||
selectedLocalFolders.remove(folder);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: FilledButton(
|
||||
onPressed: () {
|
||||
if (selectedLocalFolders.isEmpty) {
|
||||
return;
|
||||
}
|
||||
if (option == 'move') {
|
||||
for (var c in selectedComics.keys) {
|
||||
for (var s in selectedLocalFolders) {
|
||||
LocalFavoritesManager().moveFavorite(
|
||||
favPage.folder as String,
|
||||
s,
|
||||
c.id,
|
||||
(c as FavoriteItem).type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var c in selectedComics.keys) {
|
||||
for (var s in selectedLocalFolders) {
|
||||
LocalFavoritesManager().addComic(
|
||||
s,
|
||||
FavoriteItem(
|
||||
id: c.id,
|
||||
name: c.title,
|
||||
coverPath: c.cover,
|
||||
author: c.subtitle ?? '',
|
||||
type: ComicType((c.sourceKey == 'local'
|
||||
? 0
|
||||
: c.sourceKey.hashCode)),
|
||||
tags: c.tags ?? [],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
context.pop();
|
||||
updateComics();
|
||||
_cancel();
|
||||
},
|
||||
child:
|
||||
Text(option == 'move' ? "Move".tl : "Add".tl),
|
||||
).paddingVertical(16),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
App.rootContext.pop();
|
||||
updateComics();
|
||||
_cancel();
|
||||
},
|
||||
child: Text(option == 'move' ? "Move".tl : "Add".tl),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
},
|
||||
);
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -94,6 +94,9 @@ class _NormalFavoritePageState extends State<_NormalFavoritePage> {
|
||||
return ComicList(
|
||||
key: comicListKey,
|
||||
leadingSliver: SliverAppbar(
|
||||
style: context.width < changePoint
|
||||
? AppbarStyle.shadow
|
||||
: AppbarStyle.blur,
|
||||
leading: Tooltip(
|
||||
message: "Folders".tl,
|
||||
child: context.width <= _kTwoPanelChangeWidth
|
||||
@@ -211,6 +214,9 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var sliverAppBar = SliverAppbar(
|
||||
style: context.width < changePoint
|
||||
? AppbarStyle.shadow
|
||||
: AppbarStyle.blur,
|
||||
leading: Tooltip(
|
||||
message: "Folders".tl,
|
||||
child: context.width <= _kTwoPanelChangeWidth
|
||||
|
Reference in New Issue
Block a user