~repos /only-bible-app

#kotlin#android#ios

git clone https://pyrossh.dev/repos/only-bible-app.git

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


6cc6cbe6 pyrossh

2 years ago
Improve UI
lib/state.dart CHANGED
@@ -216,6 +216,7 @@ class AppModel extends ChangeNotifier {
216
216
  enableDrag: true,
217
217
  showDragHandle: true,
218
218
  useSafeArea: true,
219
+ isScrollControlled: true,
219
220
  builder: (context) => NoteSheet(verse: v),
220
221
  );
221
222
  }
@@ -363,9 +364,13 @@ class ChapterViewModel extends ChangeNotifier {
363
364
  // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Email address copied to clipboard")));
364
365
  }
365
366
 
366
- void shareVerses() {
367
+ void shareVerses(BuildContext context) {
368
+ final bible = AppModel.ofEvent(context).bible;
369
+ final name = bible.books[selectedVerses.first.book].name;
370
+ final chapter = selectedVerses.first.chapter + 1;
371
+ final title = "$name $chapter: ${selectedVerses.map((e) => e.index + 1).join(", ")}";
367
372
  final text = selectedVerses.map((e) => e.text).join("\n");
368
- Share.share(text);
373
+ Share.share("$title\n$text", subject: title);
369
374
  }
370
375
 
371
376
  pause() async {
lib/theme.dart CHANGED
@@ -1,7 +1,30 @@
1
1
  import "package:flutter/material.dart";
2
2
 
3
+ const lightColorScheme = ColorScheme.light(
4
+ background: Colors.white,
5
+ onBackground: Color(0xFF010101),
6
+ primary: Color(0xFF9A1111),
7
+ secondary: Color(0xFFFFC351),
8
+ surfaceTint: Colors.black,
9
+ shadow: Colors.black,
10
+ );
11
+
12
+ const darkColorScheme = ColorScheme.dark(
13
+ background: Color(0xFF1F1F22),
14
+ onBackground: Color(0xFFBCBEC4),
15
+ primary: Color(0xFFBC86FC),
16
+ secondary: Color(0xFFFFC351),
17
+ tertiary: Color(0xFF323232),
18
+ onTertiary: Color(0xFFBA50AB),
19
+ //E24DE2
20
+ surfaceTint: Colors.white,
21
+ shadow: Colors.white,
22
+ outline: Color(0xAA5D4979),
23
+ );
24
+
3
25
  final lightTheme = ThemeData(
4
26
  brightness: Brightness.light,
27
+ colorScheme: lightColorScheme,
5
28
  useMaterial3: true,
6
29
  fontFamily: "Roboto",
7
30
  primaryColor: const Color(0xFF602C2C),
@@ -17,6 +40,14 @@ final lightTheme = ThemeData(
17
40
  // selectionHandleColor: Colors.black,
18
41
  // selectionColor: const Color(0xAAF8D0DC),
19
42
  // ),
43
+ inputDecorationTheme: const InputDecorationTheme(
44
+ focusColor: Colors.black,
45
+ hoverColor: Colors.black,
46
+ activeIndicatorBorder: BorderSide(
47
+ color: Colors.black,
48
+ ),
49
+ hintStyle: TextStyle(color: Colors.grey),
50
+ ),
20
51
  appBarTheme: const AppBarTheme(
21
52
  backgroundColor: Colors.white,
22
53
  elevation: 0,
@@ -58,8 +89,20 @@ final lightTheme = ThemeData(
58
89
  elevation: 4,
59
90
  surfaceTintColor: Colors.transparent,
60
91
  ),
61
- colorScheme: const ColorScheme.light(
92
+ elevatedButtonTheme: ElevatedButtonThemeData(
93
+ style: TextButton.styleFrom(
94
+ elevation: 0.5,
95
+ shadowColor: Colors.black,
62
- background: Colors.white,
96
+ surfaceTintColor: Colors.white,
97
+ backgroundColor: const Color(0xFFEAE9E9),
98
+ foregroundColor: lightColorScheme.primary,
99
+ shape: const RoundedRectangleBorder(
100
+ side: BorderSide(
101
+ color: Colors.grey,
102
+ width: 1,
103
+ ),
104
+ ),
105
+ ),
63
106
  ),
64
107
  iconButtonTheme: IconButtonThemeData(
65
108
  style: IconButton.styleFrom(
@@ -74,7 +117,7 @@ final lightTheme = ThemeData(
74
117
  elevation: 0.5,
75
118
  shadowColor: Colors.black,
76
119
  backgroundColor: const Color(0xFFEAE9E9),
77
- foregroundColor: const Color(0xFF9A1111),
120
+ foregroundColor: lightColorScheme.primary,
78
121
  textStyle: const TextStyle(
79
122
  fontSize: 18,
80
123
  fontWeight: FontWeight.w500,
@@ -82,28 +125,28 @@ final lightTheme = ThemeData(
82
125
  ),
83
126
  ),
84
127
  ),
85
- textTheme: const TextTheme(
128
+ textTheme: TextTheme(
86
129
  bodyMedium: TextStyle(
87
130
  fontSize: 16,
88
131
  fontWeight: FontWeight.w400,
89
132
  wordSpacing: 0,
90
133
  letterSpacing: 0,
91
- color: Color(0xFF010101),
134
+ color: lightColorScheme.onBackground,
92
135
  ),
93
136
  bodySmall: TextStyle(
94
137
  fontSize: 14,
95
138
  fontWeight: FontWeight.w400,
96
139
  wordSpacing: 0,
97
140
  letterSpacing: 0,
98
- color: Color(0xFF010101),
141
+ color: lightColorScheme.onBackground,
99
142
  ),
100
143
  headlineLarge: TextStyle(
101
144
  fontSize: 38,
102
145
  fontWeight: FontWeight.w700,
103
- color: Color(0xFFFFB341),
146
+ color: lightColorScheme.secondary,
104
147
  ),
105
148
  headlineMedium: TextStyle(
106
- color: Color(0xFF010101),
149
+ color: lightColorScheme.onBackground,
107
150
  fontSize: 18,
108
151
  fontWeight: FontWeight.w500,
109
152
  letterSpacing: 0.5,
@@ -111,47 +154,60 @@ final lightTheme = ThemeData(
111
154
  labelMedium: TextStyle(
112
155
  fontSize: 12,
113
156
  fontWeight: FontWeight.w700,
114
- color: Color(0xFF9A1111),
157
+ color: lightColorScheme.primary,
115
158
  letterSpacing: 0,
116
159
  ),
117
160
  ),
118
161
  );
119
162
 
120
- final darkTheme = ThemeData(
163
+ final darkTheme = lightTheme.copyWith(
121
164
  brightness: Brightness.dark,
122
- fontFamily: "Roboto",
165
+ colorScheme: darkColorScheme,
123
- useMaterial3: true,
124
- visualDensity: VisualDensity.adaptivePlatformDensity,
125
166
  primaryColor: const Color(0xFF4C2323),
126
167
  primaryColorDark: const Color(0xFF3C1B1C),
127
168
  primaryColorLight: const Color(0xFF7F3D3C),
128
169
  secondaryHeaderColor: const Color(0xFFFFC351),
129
- highlightColor: const Color(0xAA5D4979),
170
+ highlightColor: darkColorScheme.outline,
130
- hoverColor: const Color(0xAA5D4979),
171
+ hoverColor: darkColorScheme.outline,
131
172
  dividerColor: Colors.white,
132
173
  shadowColor: Colors.white,
133
- appBarTheme: lightTheme.appBarTheme.copyWith(
134
- backgroundColor: const Color(0xFF1F1F22),
135
- ),
136
174
  bottomSheetTheme: lightTheme.bottomSheetTheme.copyWith(
137
175
  backgroundColor: const Color(0xFF141415),
138
176
  shadowColor: Colors.white,
139
177
  surfaceTintColor: const Color(0xFF141415),
140
178
  ),
141
- dialogTheme: const DialogTheme(
179
+ dialogTheme: DialogTheme(
180
+ backgroundColor: darkColorScheme.background,
142
181
  elevation: 1,
143
182
  shape: Border(
144
183
  top: BorderSide(
145
184
  width: 1.5,
146
- color: Color(0xAA5D4979),
185
+ color: darkColorScheme.outline,
147
186
  ),
148
187
  ),
149
188
  ),
150
189
  popupMenuTheme: lightTheme.popupMenuTheme,
190
+ elevatedButtonTheme: ElevatedButtonThemeData(
191
+ style: TextButton.styleFrom(
192
+ elevation: 0.5,
193
+ shadowColor: Colors.white,
194
+ surfaceTintColor: Colors.white,
195
+ backgroundColor: darkColorScheme.tertiary,
196
+ foregroundColor: darkColorScheme.primary,
197
+ shape: const RoundedRectangleBorder(
198
+ side: BorderSide(
199
+ color: Colors.grey,
200
+ width: 1,
201
+ ),
202
+ ),
203
+ ),
204
+ ),
151
- colorScheme: const ColorScheme.dark(
205
+ iconButtonTheme: IconButtonThemeData(
206
+ style: IconButton.styleFrom(
207
+ enableFeedback: true,
152
- background: Color(0xFF1F1F22),
208
+ foregroundColor: Colors.white,
209
+ ),
153
210
  ),
154
- iconButtonTheme: lightTheme.iconButtonTheme,
155
211
  textButtonTheme: TextButtonThemeData(
156
212
  style: ButtonStyle(
157
213
  enableFeedback: lightTheme.textButtonTheme.style!.enableFeedback,
@@ -160,25 +216,25 @@ final darkTheme = ThemeData(
160
216
  textStyle: lightTheme.textButtonTheme.style!.textStyle,
161
217
  elevation: MaterialStateProperty.all(1),
162
218
  shadowColor: MaterialStateProperty.all(Colors.white),
163
- backgroundColor: MaterialStateProperty.all(const Color(0xFF323232)),
219
+ backgroundColor: MaterialStateProperty.all(darkColorScheme.tertiary),
164
- foregroundColor: MaterialStateProperty.all(const Color(0xFFBC86FC)),
220
+ foregroundColor: MaterialStateProperty.all(darkColorScheme.primary),
165
221
  ),
166
222
  ),
167
223
  textTheme: TextTheme(
168
224
  bodyMedium: lightTheme.textTheme.bodyMedium!.copyWith(
169
- color: const Color(0xFFBCBEC4),
225
+ color: darkColorScheme.onBackground,
170
226
  ),
171
227
  bodySmall: lightTheme.textTheme.bodyMedium!.copyWith(
172
- color: const Color(0xFFBCBEC4),
228
+ color: darkColorScheme.onBackground,
173
229
  ),
174
230
  headlineLarge: lightTheme.textTheme.headlineLarge!.copyWith(
175
- color: const Color(0xFFFFC351),
231
+ color: darkColorScheme.secondary,
176
232
  ),
177
233
  headlineMedium: lightTheme.textTheme.headlineMedium!.copyWith(
178
- color: const Color(0xFFBCBEC4),
234
+ color: darkColorScheme.onBackground,
179
235
  ),
180
236
  labelMedium: lightTheme.textTheme.labelMedium!.copyWith(
181
- color: const Color(0xFFBA50AB), //E24DE2
237
+ color: darkColorScheme.onTertiary,
182
238
  ),
183
239
  ),
184
240
  );
lib/widgets/actions_sheet.dart CHANGED
@@ -61,9 +61,7 @@ class ActionsSheet extends StatelessWidget {
61
61
  IconButtonText(
62
62
  leading: IconButton(
63
63
  padding: EdgeInsets.zero,
64
- onPressed: () {
65
- model.clearSelections(context);
64
+ onPressed: () => model.clearSelections(context),
66
- },
67
65
  icon: Icon(Icons.cancel_outlined, size: 24 + iconSize, color: iconColor),
68
66
  ),
69
67
  trailing: Text("Clear", style: bodySmall),
@@ -79,9 +77,7 @@ class ActionsSheet extends StatelessWidget {
79
77
  IconButtonText(
80
78
  leading: IconButton(
81
79
  padding: EdgeInsets.zero,
82
- onPressed: () {
83
- model.onPlay(context);
80
+ onPressed: () => model.onPlay(context),
84
- },
85
81
  icon: Icon(audioIcon, size: 34 + iconSize, color: app.bible.hasAudio ? iconColor : Colors.grey),
86
82
  ),
87
83
  trailing: Text(
@@ -94,9 +90,7 @@ class ActionsSheet extends StatelessWidget {
94
90
  IconButtonText(
95
91
  leading: IconButton(
96
92
  padding: EdgeInsets.zero,
97
- onPressed: () {
98
- app.showNoteField(context, model.selectedVerses.first);
93
+ onPressed: () => app.showNoteField(context, model.selectedVerses.first),
99
- },
100
94
  icon: Icon(Icons.post_add_outlined, size: 32 + iconSize, color: iconColor),
101
95
  ),
102
96
  trailing: Text("Note", style: bodySmall),
@@ -104,7 +98,7 @@ class ActionsSheet extends StatelessWidget {
104
98
  IconButtonText(
105
99
  leading: IconButton(
106
100
  padding: EdgeInsets.zero,
107
- onPressed: model.shareVerses,
101
+ onPressed: () => model.shareVerses(context),
108
102
  icon: Icon(Icons.share_outlined, size: 28 + iconSize, color: iconColor),
109
103
  ),
110
104
  trailing: Text("Share", style: bodySmall),
lib/widgets/chapter_app_bar.dart CHANGED
@@ -47,8 +47,8 @@ class ChapterAppBar extends StatelessWidget implements PreferredSizeWidget {
47
47
  if (isDesktop)
48
48
  TextButton.icon(
49
49
  onPressed: () => app.changeBibleFromHeader(context),
50
- style: ButtonStyle(
50
+ style: TextButton.styleFrom(
51
- padding: MaterialStateProperty.all(const EdgeInsets.symmetric(horizontal: 10)),
51
+ padding: const EdgeInsets.symmetric(horizontal: 10),
52
52
  ),
53
53
  icon: const Icon(Icons.book_outlined),
54
54
  label: Text(
lib/widgets/modal_button.dart ADDED
@@ -0,0 +1,43 @@
1
+ import "package:flutter/material.dart";
2
+
3
+ class ModalButton extends StatelessWidget {
4
+ final VoidCallback onPressed;
5
+ final IconData icon;
6
+ final String label;
7
+
8
+ const ModalButton({super.key, required this.onPressed, required this.icon, required this.label});
9
+
10
+ @override
11
+ Widget build(BuildContext context) {
12
+ final theme = Theme.of(context);
13
+ return SizedBox(
14
+ width: 100,
15
+ child: TextButton.icon(
16
+ onPressed: onPressed,
17
+ icon: Icon(icon, size: 24, color: theme.colorScheme.primary),
18
+ label: Text(
19
+ label,
20
+ style: const TextStyle(
21
+ fontSize: 16,
22
+ fontWeight: FontWeight.w500,
23
+ letterSpacing: 0,
24
+ ),
25
+ ),
26
+ style: TextButton.styleFrom(
27
+ enableFeedback: true,
28
+ elevation: 0,
29
+ padding: EdgeInsets.zero,
30
+ shape: RoundedRectangleBorder(
31
+ side: BorderSide(
32
+ color: theme.colorScheme.primary,
33
+ width: 1,
34
+ ),
35
+ ),
36
+ shadowColor: theme.shadowColor,
37
+ backgroundColor: theme.colorScheme.background,
38
+ foregroundColor: theme.colorScheme.primary,
39
+ ),
40
+ ),
41
+ );
42
+ }
43
+ }
lib/widgets/note_sheet.dart CHANGED
@@ -1,6 +1,7 @@
1
1
  import "package:flutter/material.dart";
2
2
  import "package:only_bible_app/models.dart";
3
3
  import "package:only_bible_app/state.dart";
4
+ import "package:only_bible_app/widgets/modal_button.dart";
4
5
 
5
6
  class NoteSheet extends StatelessWidget {
6
7
  final Verse verse;
@@ -12,22 +13,26 @@ class NoteSheet extends StatelessWidget {
12
13
  final app = AppModel.of(context);
13
14
  return Container(
14
15
  padding: EdgeInsets.only(
15
- top: 15,
16
- left: 15,
16
+ left: 10,
17
- right: 15,
17
+ right: 10,
18
- // this will prevent the soft keyboard from covering the text fields
19
18
  bottom: MediaQuery.of(context).viewInsets.bottom + 120,
20
19
  ),
21
20
  child: Column(
22
- mainAxisSize: MainAxisSize.min,
23
- crossAxisAlignment: CrossAxisAlignment.end,
21
+ crossAxisAlignment: CrossAxisAlignment.start,
24
22
  children: [
23
+ Padding(
24
+ padding: const EdgeInsets.only(bottom: 5, left: 15),
25
+ child: Text(
26
+ "Note on ${app.bible.books[verse.book].name} ${verse.chapter + 1}:${verse.index + 1}",
27
+ style: Theme.of(context).textTheme.headlineMedium,
28
+ ),
29
+ ),
25
30
  Container(
26
31
  margin: const EdgeInsets.all(12),
27
- height: 5 * 24.0,
32
+ height: 8 * 24.0,
28
33
  child: TextField(
29
34
  controller: app.noteTextController,
30
- maxLines: 5,
35
+ maxLines: 100,
31
36
  keyboardType: TextInputType.multiline,
32
37
  decoration: const InputDecoration(filled: true, hintText: "Add a note"),
33
38
  ),
@@ -35,24 +40,32 @@ class NoteSheet extends StatelessWidget {
35
40
  const SizedBox(
36
41
  height: 20,
37
42
  ),
43
+ Padding(
44
+ padding: const EdgeInsets.symmetric(horizontal: 10),
38
- Row(
45
+ child: Row(
39
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
46
+ mainAxisAlignment: MainAxisAlignment.start,
40
- children: [
47
+ children: [
41
- if (app.noteTextController.value.text != "")
48
+ if (app.noteTextController.value.text != "")
42
- ElevatedButton(
49
+ ModalButton(
43
- onPressed: () {
44
- app.deleteNote(context, verse);
50
+ onPressed: () => app.deleteNote(context, verse),
51
+ icon: Icons.delete_outline,
52
+ label: "Delete",
45
- },
53
+ ),
54
+ Expanded(
55
+ child: Row(
56
+ mainAxisAlignment: MainAxisAlignment.end,
57
+ children: [
58
+ ModalButton(
59
+ onPressed: () => app.saveNote(context, verse),
60
+ icon: Icons.save_outlined,
46
- child: const Text("Delete"),
61
+ label: "Save",
62
+ ),
63
+ ],
64
+ ),
47
65
  ),
48
- ElevatedButton(
49
- onPressed: () {
50
- app.saveNote(context, verse);
51
- },
66
+ ],
52
- child: const Text("Save"),
53
- ),
67
+ ),
54
- ],
68
+ ),
55
- )
56
69
  ],
57
70
  ),
58
71
  );