Skip to content

Commit

Permalink
Merge pull request #332 from mateusz-bak/317-ui-improvement-idea
Browse files Browse the repository at this point in the history
feat: Expanded cover background behind AppBar
  • Loading branch information
mateusz-bak authored Sep 23, 2023
2 parents de2d450 + 77b3dd6 commit 9f33eb0
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 107 deletions.
135 changes: 84 additions & 51 deletions lib/ui/book_screen/book_screen.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:openreads/core/themes/app_theme.dart';
import 'package:openreads/generated/locale_keys.g.dart';
import 'package:openreads/logic/bloc/theme_bloc/theme_bloc.dart';
import 'package:openreads/logic/cubit/current_book_cubit.dart';
import 'package:openreads/logic/cubit/edit_book_cubit.dart';
import 'package:openreads/main.dart';
Expand Down Expand Up @@ -235,61 +237,93 @@ class BookScreen extends StatelessWidget {
];

return Scaffold(
appBar: AppBar(
actions: [
BlocBuilder<CurrentBookCubit, Book>(
builder: (context, state) {
if (moreButtonOptions.length == 1) {
if (state.deleted == true) {
moreButtonOptions.add(LocaleKeys.restore_book.tr());
moreButtonOptions.add(LocaleKeys.delete_permanently.tr());
} else {
moreButtonOptions.add(LocaleKeys.delete_book.tr());
}
}
extendBodyBehindAppBar: true,
appBar: PreferredSize(
preferredSize: AppBar().preferredSize,
// Needed to add BlocBuilder because the status bar was changing
// to different color then in BooksScreen
child: BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, state) {
final themeMode = (state as SetThemeState).themeMode;

return PopupMenuButton<String>(
onSelected: (_) {},
itemBuilder: (_) {
return moreButtonOptions.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
onTap: () async {
context.read<EditBookCubit>().setBook(state);
return AppBar(
backgroundColor: Colors.transparent,
scrolledUnderElevation: 0,
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: themeMode == ThemeMode.system
? MediaQuery.platformBrightnessOf(context) ==
Brightness.dark
? Brightness.light
: Brightness.dark
: themeMode == ThemeMode.dark
? Brightness.light
: Brightness.dark,
),
actions: [
BlocBuilder<CurrentBookCubit, Book>(
builder: (context, state) {
if (moreButtonOptions.length == 1) {
if (state.deleted == true) {
moreButtonOptions.add(LocaleKeys.restore_book.tr());
moreButtonOptions.add(
LocaleKeys.delete_permanently.tr(),
);
} else {
moreButtonOptions.add(LocaleKeys.delete_book.tr());
}
}

await Future.delayed(const Duration(
milliseconds: 0,
));
if (!context.mounted) return;
return PopupMenuButton<String>(
onSelected: (_) {},
itemBuilder: (_) {
return moreButtonOptions.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
onTap: () async {
context.read<EditBookCubit>().setBook(state);

if (choice == moreButtonOptions[0]) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const AddBookScreen(
editingExistingBook: true,
),
),
await Future.delayed(const Duration(
milliseconds: 0,
));
if (!context.mounted) return;

if (choice == moreButtonOptions[0]) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const AddBookScreen(
editingExistingBook: true,
),
),
);
} else if (choice == moreButtonOptions[1]) {
if (state.deleted == false) {
_showDeleteRestoreDialog(
context, true, null, state);
} else {
_showDeleteRestoreDialog(
context, false, null, state);
}
} else if (choice == moreButtonOptions[2]) {
_showDeleteRestoreDialog(
context,
true,
true,
state,
);
}
},
);
} else if (choice == moreButtonOptions[1]) {
if (state.deleted == false) {
_showDeleteRestoreDialog(
context, true, null, state);
} else {
_showDeleteRestoreDialog(
context, false, null, state);
}
} else if (choice == moreButtonOptions[2]) {
_showDeleteRestoreDialog(context, true, true, state);
}
}).toList();
},
);
}).toList();
},
);
},
),
],
},
),
],
);
},
),
),
body: BlocBuilder<CurrentBookCubit, Book>(
builder: (context, state) {
Expand All @@ -299,14 +333,13 @@ class BookScreen extends StatelessWidget {
(state.hasCover == true)
? Center(
child: CoverView(
onPressed: null,
heroTag: heroTag,
book: state,
),
)
: const SizedBox(),
Padding(
padding: const EdgeInsets.all(5),
padding: const EdgeInsets.fromLTRB(5, 0, 5, 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expand Down
52 changes: 30 additions & 22 deletions lib/ui/book_screen/widgets/cover_background.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:blurhash_dart/blurhash_dart.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:openreads/core/themes/app_theme.dart';
import 'package:openreads/logic/cubit/current_book_cubit.dart';
import 'package:openreads/model/book.dart';
import 'package:image/image.dart' as img;
Expand All @@ -18,29 +19,36 @@ class CoverBackground extends StatelessWidget {
builder: (context, state) {
final image = BlurHash.decode(state.blurHash!).toImage(35, 20);

return Image.memory(
Uint8List.fromList(
img.encodeJpg(image),
return ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(cornerRadius),
bottomRight: Radius.circular(cornerRadius),
),
child: Image.memory(
Uint8List.fromList(
img.encodeJpg(image),
),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
height: (MediaQuery.of(context).size.height / 2.5) +
MediaQuery.of(context).padding.top,
frameBuilder: (
BuildContext context,
Widget child,
int? frame,
bool wasSynchronouslyLoaded,
) {
if (wasSynchronouslyLoaded) {
return child;
}
return AnimatedOpacity(
opacity: frame == null ? 0 : 0.8,
duration: const Duration(milliseconds: 400),
curve: Curves.easeIn,
child: child,
);
},
),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 2.5,
frameBuilder: (
BuildContext context,
Widget child,
int? frame,
bool wasSynchronouslyLoaded,
) {
if (wasSynchronouslyLoaded) {
return child;
}
return AnimatedOpacity(
opacity: frame == null ? 0 : 0.8,
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
child: child,
);
},
);
},
);
Expand Down
72 changes: 38 additions & 34 deletions lib/ui/book_screen/widgets/cover_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ class CoverView extends StatefulWidget {
const CoverView({
Key? key,
this.heroTag,
this.onPressed,
this.book,
this.coverFile,
this.blurHashString,
}) : super(key: key);

final Function()? onPressed;
final String? heroTag;
final String? blurHashString;
final Book? book;
Expand All @@ -39,43 +37,49 @@ class _CoverViewState extends State<CoverView> {
@override
Widget build(BuildContext context) {
_loadCoverFile();
final mediaQuery = MediaQuery.of(context);

return InkWell(
onTap: widget.onPressed,
child: Stack(
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 2.5,
child: const Stack(
children: [
CoverBackground(),
],
),
return Stack(
children: [
SizedBox(
width: mediaQuery.size.width,
height: (mediaQuery.size.height / 2.5) + mediaQuery.padding.top,
child: const Stack(
children: [
CoverBackground(),
],
),
Center(
child: SizedBox(
height: ((MediaQuery.of(context).size.height / 2.5) - 0),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(cornerRadius),
child: coverFile != null
? Hero(
tag: widget.heroTag ?? "",
child: Image.file(
coverFile!,
fit: BoxFit.cover,
height:
(MediaQuery.of(context).size.height / 2.5) - 40,
),
)
: const SizedBox(),
),
Column(
children: [
SizedBox(height: mediaQuery.padding.top),
Center(
child: SizedBox(
height: mediaQuery.size.height / 2.5,
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(cornerRadius),
child: coverFile != null
? Hero(
tag: widget.heroTag ?? "",
child: Image.file(
coverFile!,
fit: BoxFit.cover,
height: mediaQuery.size.height / 2.5,
),
)
: const SizedBox(),
),
),
),
),
),
),
],
),
const SizedBox(height: 10),
],
),
],
);
}
}

0 comments on commit 9f33eb0

Please sign in to comment.