Add AppbarStyle.shadow;

Improve favorites page ui.
This commit is contained in:
2024-11-23 12:12:52 +08:00
parent a1474ca9c3
commit c2b8760d86
6 changed files with 219 additions and 200 deletions

View File

@@ -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;
}
}

View File

@@ -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),
),

View File

@@ -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';

View File

@@ -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),
),
),
),
));
},
);
},
],
),
),
),
);
},
),
);
}

View File

@@ -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