~repos /only-bible-app

#kotlin#android#ios

GIT_CONFIG_PARAMETERS="'http.version=HTTP/1.1'" git clone https://git.pyrossh.dev/only-bible-app.git
Discussions: https://groups.google.com/g/rust-embed-devs

The only bible app you will ever need. No ads. No in-app purchases. No distractions.



lib/widgets/book_select_sheet.dart



import "package:flutter/material.dart";
import "package:only_bible_app/gen/bible.gen.dart";
import "package:only_bible_app/store/app_state.dart";
import "package:only_bible_app/utils.dart";
import "package:only_bible_app/widgets/book_tile.dart";
class BookSelectSheet extends StatefulWidget {
final Bible bible;
final BuildContext parentContext;
final void Function(int bookIndex, int chapterIndex) onChapterSelected;
final Book? initialBook;
const BookSelectSheet({
super.key,
required this.bible,
required this.parentContext,
required this.onChapterSelected,
this.initialBook,
});
@override
State<BookSelectSheet> createState() => _BookSelectSheetState();
}
class _BookSelectSheetState extends State<BookSelectSheet> {
late bool showOldTestament;
late PageController _pageController;
Book? _selectedBook;
@override
void initState() {
super.initState();
final currentBook = widget.parentContext.read().savedBook;
showOldTestament = currentBook < 39;
_selectedBook = widget.initialBook;
_pageController = PageController(initialPage: _selectedBook != null ? 1 : 0);
}
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
void _onBookTapped(Book book) {
if (book.chapters!.length == 1) {
widget.onChapterSelected(book.index, 0);
return;
}
setState(() => _selectedBook = book);
_pageController.animateToPage(
1,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
void _onBackToBooks() {
_pageController.animateToPage(
0,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
@override
Widget build(BuildContext context) {
final currentBook = widget.parentContext.read().savedBook;
final currentChapter = widget.parentContext.read().savedChapter;
return PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(),
children: [
// Page 0: Book selection
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
ToggleButtons(
onPressed: (int index) {
setState(() {
showOldTestament = index == 0;
});
},
textStyle: Theme.of(context).textTheme.labelLarge,
isSelected: [showOldTestament, !showOldTestament],
children: [
Text(widget.bible.oldTestamentTitle!),
Text(widget.bible.newTestamentTitle!),
],
),
const SizedBox(height: 12),
Expanded(
child: GridView.count(
crossAxisCount: 6,
crossAxisSpacing: 6,
mainAxisSpacing: 6,
children: (showOldTestament ? widget.bible.getOldBooks() : widget.bible.getNewBooks())
.map((book) => BookTile(
label: book.shortName(book.name!),
isSelected: currentBook == book.index,
onTap: () => _onBookTapped(book)))
.toList(),
),
),
],
),
),
// Page 1: Chapter selection
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
Row(
children: [
IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: _onBackToBooks,
),
Text(
_selectedBook?.name ?? "",
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
const SizedBox(height: 12),
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 6,
crossAxisSpacing: 6,
mainAxisSpacing: 6,
),
itemCount: _selectedBook?.chapters?.length ?? 0,
itemBuilder: (_, index) {
final isSelected = currentBook == _selectedBook?.index && currentChapter == index;
return BookTile(
label: "${index + 1}",
isSelected: isSelected,
onTap: () => widget.onChapterSelected(_selectedBook!.index, index),
);
},
),
),
],
),
),
],
);
}
}