Skip to content

Commit c40f525

Browse files
Work on bookmarks
1 parent 329d872 commit c40f525

7 files changed

Lines changed: 233 additions & 0 deletions

File tree

lib/common/colors.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import 'package:flutter/material.dart';
2+
3+
// From https://stackoverflow.com/a/76053830/ (CC BY-SA 4.0)
4+
extension StringColor on String {
5+
Color textToColor() {
6+
if (isEmpty) {
7+
return Colors.black;
8+
}
9+
var hash = 0;
10+
for (var i = 0; i < length; i++) {
11+
hash = codeUnitAt(i) + ((hash << 5) - hash);
12+
}
13+
return Color(hash + 0xFF000000);
14+
}
15+
}

lib/services/settings_service.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class SettingsService with ListenableServiceMixin {
1414
_sectionNumber,
1515
_recentBooks,
1616
_viewBy,
17+
_bookmarks,
1718
]);
1819
}
1920

@@ -31,6 +32,9 @@ class SettingsService with ListenableServiceMixin {
3132
static const _kNavRecentBooks = 'NAV_RECENT_BOOKS';
3233
static const _kNavViewBy = 'NAV_VIEW_BY';
3334

35+
// Bookmarks
36+
static const _kBookmarks = 'BOOKMARKS';
37+
3438
// Reader view specifics
3539
static const _kTextScaling = 'TEXT_SCALING';
3640
static const _kShowMarks = 'SHOW_MARKS';
@@ -56,6 +60,9 @@ class SettingsService with ListenableServiceMixin {
5660
ViewBy _viewBy = ViewBy.section;
5761
ViewBy get viewBy => _viewBy;
5862

63+
List<String> _bookmarks = [];
64+
List<String> get bookmarks => _bookmarks;
65+
5966
double _textScaling = 1.0;
6067
double get textScaling => _textScaling;
6168
bool _showMarks = true;
@@ -74,6 +81,7 @@ class SettingsService with ListenableServiceMixin {
7481
_sectionNumber = await getSectionNumber();
7582
_recentBooks = await getNavRecentBooks();
7683
_viewBy = await getNavViewBy();
84+
_bookmarks = await getBookmarks();
7785
_textScaling = await getTextScaling();
7886
_showMarks = await getShowMarks();
7987
_showChaptersAndVerses = await getShowChaptersAndVerses();
@@ -205,6 +213,20 @@ class SettingsService with ListenableServiceMixin {
205213
return _viewBy;
206214
}
207215

216+
// Bookmarks
217+
Future<void> setBookmarks(List<String> value) async {
218+
_recentBooks = value;
219+
SharedPreferences prefs = await SharedPreferences.getInstance();
220+
prefs.setStringList(_kBookmarks, value);
221+
notifyListeners();
222+
}
223+
224+
Future<List<String>> getBookmarks() async {
225+
SharedPreferences prefs = await SharedPreferences.getInstance();
226+
_bookmarks = prefs.getStringList(_kBookmarks) ?? [];
227+
return _bookmarks;
228+
}
229+
208230
// Text scaling
209231
Future<void> setTextScaling(double value) async {
210232
_textScaling = value;
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:phosphor_flutter/phosphor_flutter.dart';
3+
import 'package:stacked/stacked.dart';
4+
5+
import '../../../common/colors.dart';
6+
import '../../../common/themes.dart';
7+
import '../../common/ui_helpers.dart';
8+
import 'bookmarks_viewmodel.dart';
9+
10+
class BookmarksView extends StackedView<BookmarksViewModel> {
11+
const BookmarksView({super.key});
12+
13+
@override
14+
Widget builder(
15+
BuildContext context,
16+
BookmarksViewModel viewModel,
17+
Widget? child,
18+
) {
19+
bool isPortrait = isPortraitOrientation(context);
20+
return PopScope(
21+
canPop: false,
22+
onPopInvoked: viewModel.onPopInvoked,
23+
child: Scaffold(
24+
backgroundColor: context.theme.appColors.background,
25+
appBar: AppBar(
26+
backgroundColor: context.theme.appColors.background,
27+
centerTitle: true,
28+
scrolledUnderElevation: 0.0,
29+
title: isPortrait
30+
? null
31+
: Text(
32+
'Your Bookmarks',
33+
style: TextStyle(
34+
color: context.theme.appColors.primary,
35+
fontSize: 18.0,
36+
fontWeight: FontWeight.w500,
37+
),
38+
),
39+
),
40+
body: Container(
41+
padding: EdgeInsets.only(top: isPortrait ? 26.0 : 0.0),
42+
child: Column(
43+
mainAxisSize: MainAxisSize.min,
44+
children: [
45+
if (isPortrait)
46+
Padding(
47+
padding: const EdgeInsets.only(bottom: 36.0),
48+
child: Text(
49+
'Your Bookmarks',
50+
style: TextStyle(
51+
color: context.theme.appColors.primary,
52+
fontSize: 26.0,
53+
fontWeight: FontWeight.bold,
54+
),
55+
),
56+
),
57+
viewModel.bookmarks.isEmpty
58+
? Row(
59+
mainAxisAlignment: MainAxisAlignment.center,
60+
children: [
61+
Padding(
62+
padding: const EdgeInsets.symmetric(vertical: 40.0, horizontal: 25.0),
63+
child: Text(
64+
'No bookmarks yet.',
65+
style: TextStyle(
66+
color: context.theme.appColors.primary,
67+
fontSize: 15.0,
68+
),
69+
),
70+
),
71+
],
72+
)
73+
: Expanded(
74+
child: ListView.builder(
75+
itemCount: viewModel.bookmarks.length,
76+
itemBuilder: (BuildContext context, int index) {
77+
return InkWell(
78+
onTap: () => {},
79+
child: Padding(
80+
padding: const EdgeInsets.symmetric(vertical: 14.0, horizontal: 25.0),
81+
child: Row(
82+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
83+
crossAxisAlignment: CrossAxisAlignment.center,
84+
children: [
85+
Row(
86+
crossAxisAlignment: CrossAxisAlignment.center,
87+
children: [
88+
PhosphorIcon(
89+
PhosphorIcons.bookmarkSimple(PhosphorIconsStyle.bold),
90+
color: viewModel.bookmarks[index].textToColor(),
91+
size: 20.0,
92+
),
93+
const SizedBox(width: 12.0),
94+
Text(
95+
viewModel.bookmarks[index],
96+
style: TextStyle(
97+
color: context.theme.appColors.primary,
98+
fontSize: 16.0,
99+
fontWeight: FontWeight.w500,
100+
),
101+
),
102+
],
103+
),
104+
PhosphorIcon(
105+
PhosphorIcons.caretRight(PhosphorIconsStyle.bold),
106+
color: context.theme.appColors.primary,
107+
size: 18.0,
108+
semanticLabel: 'Caret right',
109+
),
110+
],
111+
),
112+
),
113+
);
114+
},
115+
),
116+
),
117+
],
118+
),
119+
),
120+
),
121+
);
122+
}
123+
124+
@override
125+
BookmarksViewModel viewModelBuilder(
126+
BuildContext context,
127+
) =>
128+
BookmarksViewModel();
129+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'package:stacked/stacked.dart';
2+
import 'package:stacked_services/stacked_services.dart';
3+
4+
import '../../../app/app.locator.dart';
5+
import '../../../app/app.router.dart';
6+
import '../../../services/settings_service.dart';
7+
8+
class BookmarksViewModel extends BaseViewModel {
9+
final _settingsService = locator<SettingsService>();
10+
final _navigationService = locator<NavigationService>();
11+
12+
List<String> get bookmarks => _settingsService.bookmarks;
13+
14+
void deleteBookmark(String bookmark) async {
15+
List<String> allBookmarks = List.from(bookmarks);
16+
allBookmarks.remove(bookmark);
17+
await _settingsService.setBookmarks(allBookmarks);
18+
}
19+
20+
void onPopInvoked(bool onPopInvoked) async {
21+
_navigationService.clearStackAndShow(Routes.readerView);
22+
}
23+
}

lib/ui/widgets/common/side_navigation_drawer/side_navigation_drawer.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,35 @@ class SideNavigationDrawer extends StackedView<SideNavigationDrawerModel> {
8383
),
8484
),
8585
),
86+
InkWell(
87+
onTap: () {
88+
closeNavigation();
89+
viewModel.onTapBookmarks();
90+
},
91+
child: Padding(
92+
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 2.0),
93+
child: Row(
94+
mainAxisAlignment: MainAxisAlignment.start,
95+
mainAxisSize: MainAxisSize.max,
96+
children: [
97+
PhosphorIcon(
98+
PhosphorIcons.bookmarksSimple(PhosphorIconsStyle.regular),
99+
color: context.theme.appColors.primaryOnDark,
100+
size: 24.0,
101+
),
102+
const SizedBox(width: 12.0),
103+
Text(
104+
'Bookmarks',
105+
style: TextStyle(
106+
color: context.theme.appColors.primaryOnDark,
107+
fontSize: 16.0,
108+
fontWeight: FontWeight.w500,
109+
),
110+
),
111+
],
112+
),
113+
),
114+
),
86115
InkWell(
87116
onTap: () {
88117
closeNavigation();

lib/ui/widgets/common/side_navigation_drawer/side_navigation_drawer_model.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ class SideNavigationDrawerModel extends BaseViewModel {
1111
_navigationService.clearStackAndShow(Routes.searchView);
1212
}
1313

14+
void onTapBookmarks() {
15+
_navigationService.clearStackAndShow(Routes.bookmarksView);
16+
}
17+
1418
void onTapSettings() {
1519
_navigationService.clearStackAndShow(Routes.settingsView);
1620
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:bible_side/app/app.locator.dart';
3+
4+
import '../helpers/test_helpers.dart';
5+
6+
void main() {
7+
group('BookmarksViewModel Tests -', () {
8+
setUp(() => registerServices());
9+
tearDown(() => locator.reset());
10+
});
11+
}

0 commit comments

Comments
 (0)