Vaani/lib/shared/widgets/shelves/home_shelf.dart

119 lines
3.7 KiB
Dart
Raw Normal View History

2024-05-08 21:25:06 -04:00
import 'dart:math';
2024-05-08 05:03:49 -04:00
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shelfsdk/audiobookshelf_api.dart';
2024-06-16 22:24:32 -04:00
import 'package:whispering_pages/shared/extensions/model_conversions.dart';
2024-05-14 10:11:25 -04:00
import 'package:whispering_pages/shared/widgets/shelves/author_shelf.dart';
import 'package:whispering_pages/shared/widgets/shelves/book_shelf.dart';
2024-05-08 05:03:49 -04:00
/// A shelf that displays books/authors/series on the home page
///
/// this will build the appropriate shelf based on the type of the shelf
class HomeShelf extends HookConsumerWidget {
const HomeShelf({
super.key,
required this.shelf,
required this.title,
});
2024-05-08 21:25:06 -04:00
final String title;
2024-05-08 05:03:49 -04:00
final Shelf shelf;
@override
Widget build(BuildContext context, WidgetRef ref) {
return switch (shelf.type) {
ShelfType.book => BookHomeShelf(
title: title,
2024-06-16 22:24:32 -04:00
shelf: shelf.asLibraryItemShelf,
2024-05-08 05:03:49 -04:00
),
ShelfType.authors => AuthorHomeShelf(
title: title,
2024-06-16 22:24:32 -04:00
shelf: shelf.asAuthorShelf,
2024-05-08 05:03:49 -04:00
),
_ => Container(),
};
}
}
2024-05-08 21:25:06 -04:00
/// A shelf that displays children on the home page
2024-05-08 05:03:49 -04:00
class SimpleHomeShelf extends HookConsumerWidget {
const SimpleHomeShelf({
super.key,
required this.children,
required this.title,
2024-05-08 21:25:06 -04:00
this.height,
2024-05-08 05:03:49 -04:00
});
2024-05-08 21:25:06 -04:00
/// the title of the shelf
final String title;
/// the children to display on the shelf
2024-05-08 05:03:49 -04:00
final List<Widget> children;
2024-05-08 21:25:06 -04:00
final double? height;
2024-05-08 05:03:49 -04:00
@override
Widget build(BuildContext context, WidgetRef ref) {
2024-05-08 21:25:06 -04:00
// if height is null take up 30% of the smallest screen dimension
2024-05-08 05:03:49 -04:00
return Padding(
2024-05-12 05:38:30 -04:00
padding: const EdgeInsets.symmetric(vertical: 8.0),
2024-05-08 05:03:49 -04:00
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
2024-05-12 05:38:30 -04:00
Padding(
padding: const EdgeInsets.only(left: 8.0, bottom: 8.0),
2024-08-23 03:44:44 -04:00
child: Text(title, style: Theme.of(context).textTheme.titleMedium),
2024-05-12 05:38:30 -04:00
),
// fix the height of the shelf as a percentage of the screen height
2024-05-08 21:25:06 -04:00
SizedBox(
2024-05-12 05:38:30 -04:00
height: height ?? getDefaultShelfHeight(context, perCent: 0.5),
2024-05-08 21:25:06 -04:00
child: ListView.separated(
scrollDirection: Axis.horizontal,
2024-05-12 05:38:30 -04:00
itemBuilder: (context, index) {
if (index == 0 || index == children.length + 1) {
return const SizedBox(
width: 8,
);
}
return children[index - 1];
},
separatorBuilder: (context, index) {
if (index == 0 || index == children.length + 1) {
return const SizedBox();
}
2024-06-17 01:33:56 -04:00
return const SizedBox(width: 4);
2024-05-12 05:38:30 -04:00
},
itemCount: children.length +
2, // add some extra space at the start and end so that the first and last items are not at the edge
2024-05-08 05:03:49 -04:00
),
),
],
),
);
}
2024-05-12 05:38:30 -04:00
/// get the height of the shelf based on the screen size
/// the height is the height parent wants the shelf to be
/// but it should not be less than 150 so we take the max of 150 and the height in the end
/// ignoreWidth is used to ignore the width of the screen and take only the height into consideration else smallest side is taken so that shelf is not too big on tablets
double getDefaultShelfHeight(
BuildContext context, {
bool ignoreWidth = false,
atMin = 150.0,
perCent = 0.3,
}) {
double referenceSide;
if (ignoreWidth) {
referenceSide = MediaQuery.of(context).size.height;
} else {
referenceSide = min(
MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height,
);
}
return max(atMin, referenceSide * perCent);
}
2024-05-08 05:03:49 -04:00
}