diff --git a/lib/components/appbar.dart b/lib/components/appbar.dart index 80c67f7..c5341f1 100644 --- a/lib/components/appbar.dart +++ b/lib/components/appbar.dart @@ -115,6 +115,11 @@ class _AppbarState extends State { } } +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; } } diff --git a/lib/components/comic.dart b/lib/components/comic.dart index 488fd70..28d53a7 100644 --- a/lib/components/comic.dart +++ b/lib/components/comic.dart @@ -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), ), diff --git a/lib/pages/favorites/favorites_page.dart b/lib/pages/favorites/favorites_page.dart index afdf3b6..f71eb17 100644 --- a/lib/pages/favorites/favorites_page.dart +++ b/lib/pages/favorites/favorites_page.dart @@ -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'; diff --git a/lib/pages/favorites/local_favorites_page.dart b/lib/pages/favorites/local_favorites_page.dart index 1a9d784..d412c75 100644 --- a/lib/pages/favorites/local_favorites_page.dart +++ b/lib/pages/favorites/local_favorites_page.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), + ), ), - ), - )); - }, - ); - }, + ], + ), + ), + ), + ); + }, + ), ); } diff --git a/lib/pages/favorites/network_favorites_page.dart b/lib/pages/favorites/network_favorites_page.dart index b11e803..c382b09 100644 --- a/lib/pages/favorites/network_favorites_page.dart +++ b/lib/pages/favorites/network_favorites_page.dart @@ -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 diff --git a/pubspec.lock b/pubspec.lock index 4a58d34..eb64a71 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -393,8 +393,8 @@ packages: dependency: "direct main" description: path: "." - ref: HEAD - resolved-ref: "51a27e2ca0e05becfb8ee3a506294dc4460721a8" + ref: "829a566b738a26ea98e523807f49838e21308543" + resolved-ref: "829a566b738a26ea98e523807f49838e21308543" url: "https://github.com/pkuislm/flutter_saf.git" source: git version: "0.0.1"