+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/02-set-up-firebase/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/compiler.xml b/02-set-up-firebase/Final/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/gradle.xml b/02-set-up-firebase/Final/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/02-set-up-firebase/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/jarRepositories.xml b/02-set-up-firebase/Final/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/misc.xml b/02-set-up-firebase/Final/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/.idea/modules.xml b/02-set-up-firebase/Final/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/build.gradle b/02-set-up-firebase/Final/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/google-services.json b/02-set-up-firebase/Final/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/proguard-rules.pro b/02-set-up-firebase/Final/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/AndroidManifest.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..0f61a9e
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // TODO: Implement onEvent
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ // TODO: Call startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ // TODO: Implement onDocumentAdded
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ // TODO: Implement onDocumentModified
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ // TODO: Implement
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..e121205
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ init {
+ // TODO: Create the Query for accessing data
+ }
+
+ fun addBooksClicked() {
+ // TODO: Implement Add Books
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ // TODO: Implement Update Book
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/activity_main.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/item_book.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/colors.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/strings.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/styles.xml b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/build.gradle b/02-set-up-firebase/Final/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/gradle.properties b/02-set-up-firebase/Final/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/02-set-up-firebase/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/02-set-up-firebase/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/02-set-up-firebase/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/02-set-up-firebase/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/02-set-up-firebase/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/02-set-up-firebase/Final/Bookshelf/gradlew b/02-set-up-firebase/Final/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/02-set-up-firebase/Final/Bookshelf/gradlew.bat b/02-set-up-firebase/Final/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/02-set-up-firebase/Final/Bookshelf/settings.gradle b/02-set-up-firebase/Final/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/02-set-up-firebase/Final/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/.gitignore b/02-set-up-firebase/Starter/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/codeStyles/Project.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/compiler.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/gradle.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/jarRepositories.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/misc.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/.idea/modules.xml b/02-set-up-firebase/Starter/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/build.gradle b/02-set-up-firebase/Starter/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/proguard-rules.pro b/02-set-up-firebase/Starter/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/AndroidManifest.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..0f61a9e
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // TODO: Implement onEvent
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ // TODO: Call startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ // TODO: Implement onDocumentAdded
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ // TODO: Implement onDocumentModified
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ // TODO: Implement
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..e121205
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ init {
+ // TODO: Create the Query for accessing data
+ }
+
+ fun addBooksClicked() {
+ // TODO: Implement Add Books
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ // TODO: Implement Update Book
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/item_book.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/colors.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/strings.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/styles.xml b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/build.gradle b/02-set-up-firebase/Starter/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/gradle.properties b/02-set-up-firebase/Starter/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/02-set-up-firebase/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/02-set-up-firebase/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/02-set-up-firebase/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/02-set-up-firebase/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/02-set-up-firebase/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/02-set-up-firebase/Starter/Bookshelf/gradlew b/02-set-up-firebase/Starter/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/02-set-up-firebase/Starter/Bookshelf/gradlew.bat b/02-set-up-firebase/Starter/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/02-set-up-firebase/Starter/Bookshelf/settings.gradle b/02-set-up-firebase/Starter/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/02-set-up-firebase/Starter/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/.gitignore b/05-write-data-to-firestore/Final/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/codeStyles/Project.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/compiler.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/gradle.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/jarRepositories.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/misc.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/.idea/modules.xml b/05-write-data-to-firestore/Final/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/build.gradle b/05-write-data-to-firestore/Final/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/google-services.json b/05-write-data-to-firestore/Final/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/proguard-rules.pro b/05-write-data-to-firestore/Final/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/AndroidManifest.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..0f61a9e
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // TODO: Implement onEvent
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ // TODO: Call startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ // TODO: Implement onDocumentAdded
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ // TODO: Implement onDocumentModified
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ // TODO: Implement
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..7d2ba15
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ // TODO: Create the Query for accessing data
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ // TODO: Implement Update Book
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/activity_main.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/item_book.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/colors.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/strings.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/styles.xml b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/build.gradle b/05-write-data-to-firestore/Final/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/gradle.properties b/05-write-data-to-firestore/Final/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/05-write-data-to-firestore/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/05-write-data-to-firestore/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/05-write-data-to-firestore/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/05-write-data-to-firestore/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/05-write-data-to-firestore/Final/Bookshelf/gradlew b/05-write-data-to-firestore/Final/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/05-write-data-to-firestore/Final/Bookshelf/gradlew.bat b/05-write-data-to-firestore/Final/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/05-write-data-to-firestore/Final/Bookshelf/settings.gradle b/05-write-data-to-firestore/Final/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/05-write-data-to-firestore/Final/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/.gitignore b/05-write-data-to-firestore/Starter/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/codeStyles/Project.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/compiler.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/gradle.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/jarRepositories.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/misc.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/.idea/modules.xml b/05-write-data-to-firestore/Starter/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/build.gradle b/05-write-data-to-firestore/Starter/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/google-services.json b/05-write-data-to-firestore/Starter/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/proguard-rules.pro b/05-write-data-to-firestore/Starter/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/AndroidManifest.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..0f61a9e
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // TODO: Implement onEvent
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ // TODO: Call startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ // TODO: Implement onDocumentAdded
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ // TODO: Implement onDocumentModified
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ // TODO: Implement
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..e121205
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ init {
+ // TODO: Create the Query for accessing data
+ }
+
+ fun addBooksClicked() {
+ // TODO: Implement Add Books
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ // TODO: Implement Update Book
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/item_book.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/colors.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/strings.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/styles.xml b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/build.gradle b/05-write-data-to-firestore/Starter/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/gradle.properties b/05-write-data-to-firestore/Starter/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/05-write-data-to-firestore/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/05-write-data-to-firestore/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/05-write-data-to-firestore/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/gradlew b/05-write-data-to-firestore/Starter/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/gradlew.bat b/05-write-data-to-firestore/Starter/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/05-write-data-to-firestore/Starter/Bookshelf/settings.gradle b/05-write-data-to-firestore/Starter/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/05-write-data-to-firestore/Starter/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/.gitignore b/06-firestore-eventlistener/Final/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/codeStyles/Project.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/compiler.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/gradle.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/jarRepositories.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/misc.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/.idea/modules.xml b/06-firestore-eventlistener/Final/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/build.gradle b/06-firestore-eventlistener/Final/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/google-services.json b/06-firestore-eventlistener/Final/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/proguard-rules.pro b/06-firestore-eventlistener/Final/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/AndroidManifest.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..ea5a312
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // Handle errors
+ if (error != null) {
+ Log.w(TAG, "onEvent:error", error)
+ onError(error)
+ return
+ }
+
+ if (documentSnapshots == null) {
+ return
+ }
+
+ for (change in documentSnapshots.documentChanges) {
+ when (change.type) {
+ DocumentChange.Type.ADDED -> {
+ onDocumentAdded(change)
+ }
+ DocumentChange.Type.MODIFIED -> {
+
+ }
+ DocumentChange.Type.REMOVED -> {
+
+ }
+ }
+ }
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ snapshots.add(change.newIndex, change.document)
+ notifyItemInserted(change.newIndex)
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ // TODO: Implement onDocumentModified
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ if (query != null && registration == null) {
+ registration = query?.addSnapshotListener(this)
+ }
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..258e159
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .orderBy(Book.FIELD_RATING, Query.Direction.DESCENDING)
+ .limit(MainActivity.BOOK_QUERY_LIMIT);
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ // TODO: Implement Update Book
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/activity_main.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/item_book.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/colors.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/strings.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/styles.xml b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/build.gradle b/06-firestore-eventlistener/Final/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/gradle.properties b/06-firestore-eventlistener/Final/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/06-firestore-eventlistener/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/06-firestore-eventlistener/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/06-firestore-eventlistener/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/06-firestore-eventlistener/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/06-firestore-eventlistener/Final/Bookshelf/gradlew b/06-firestore-eventlistener/Final/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/06-firestore-eventlistener/Final/Bookshelf/gradlew.bat b/06-firestore-eventlistener/Final/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/06-firestore-eventlistener/Final/Bookshelf/settings.gradle b/06-firestore-eventlistener/Final/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/06-firestore-eventlistener/Final/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/.gitignore b/06-firestore-eventlistener/Starter/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/codeStyles/Project.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/compiler.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/gradle.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/jarRepositories.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/misc.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/.idea/modules.xml b/06-firestore-eventlistener/Starter/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/build.gradle b/06-firestore-eventlistener/Starter/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/google-services.json b/06-firestore-eventlistener/Starter/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/proguard-rules.pro b/06-firestore-eventlistener/Starter/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/AndroidManifest.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..0f61a9e
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // TODO: Implement onEvent
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ // TODO: Call startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ // TODO: Implement onDocumentAdded
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ // TODO: Implement onDocumentModified
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ // TODO: Implement
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..7d2ba15
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ // TODO: Create the Query for accessing data
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ // TODO: Implement Update Book
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/item_book.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/colors.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/strings.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/styles.xml b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/build.gradle b/06-firestore-eventlistener/Starter/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/gradle.properties b/06-firestore-eventlistener/Starter/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/06-firestore-eventlistener/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/06-firestore-eventlistener/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/06-firestore-eventlistener/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/gradlew b/06-firestore-eventlistener/Starter/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/gradlew.bat b/06-firestore-eventlistener/Starter/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/06-firestore-eventlistener/Starter/Bookshelf/settings.gradle b/06-firestore-eventlistener/Starter/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/06-firestore-eventlistener/Starter/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/.gitignore b/07-updating-data/Final/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/07-updating-data/Final/Bookshelf/.idea/codeStyles/Project.xml b/07-updating-data/Final/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/07-updating-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/compiler.xml b/07-updating-data/Final/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/gradle.xml b/07-updating-data/Final/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/07-updating-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/jarRepositories.xml b/07-updating-data/Final/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/misc.xml b/07-updating-data/Final/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/.idea/modules.xml b/07-updating-data/Final/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/build.gradle b/07-updating-data/Final/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/google-services.json b/07-updating-data/Final/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/proguard-rules.pro b/07-updating-data/Final/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/AndroidManifest.xml b/07-updating-data/Final/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..c618800
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // Handle errors
+ if (error != null) {
+ Log.w(TAG, "onEvent:error", error)
+ onError(error)
+ return
+ }
+
+ if (documentSnapshots == null) {
+ return
+ }
+
+ for (change in documentSnapshots.documentChanges) {
+ when (change.type) {
+ DocumentChange.Type.ADDED -> {
+ onDocumentAdded(change)
+ }
+ DocumentChange.Type.MODIFIED -> {
+ onDocumentModified(change)
+ }
+ DocumentChange.Type.REMOVED -> {
+
+ }
+ }
+ }
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ snapshots.add(change.newIndex, change.document)
+ notifyItemInserted(change.newIndex)
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ if (change.oldIndex == change.newIndex) {
+ // Item changed but remained in same position
+ snapshots[change.oldIndex] = change.document
+ notifyItemChanged(change.oldIndex)
+ } else {
+ // Item changed and changed position
+ snapshots.removeAt(change.oldIndex)
+ snapshots.add(change.newIndex, change.document)
+ notifyItemMoved(change.oldIndex, change.newIndex)
+ }
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ if (query != null && registration == null) {
+ registration = query?.addSnapshotListener(this)
+ }
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..5b956a2
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .orderBy(Book.FIELD_RATING, Query.Direction.DESCENDING)
+ .limit(MainActivity.BOOK_QUERY_LIMIT);
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .document(document.id)
+ .update(Book.FIELD_TITLE, newTitle)
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/values/colors.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/values/strings.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/app/src/main/res/values/styles.xml b/07-updating-data/Final/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/build.gradle b/07-updating-data/Final/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/gradle.properties b/07-updating-data/Final/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/07-updating-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/07-updating-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/07-updating-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/07-updating-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/07-updating-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/07-updating-data/Final/Bookshelf/gradlew b/07-updating-data/Final/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/07-updating-data/Final/Bookshelf/gradlew.bat b/07-updating-data/Final/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/07-updating-data/Final/Bookshelf/settings.gradle b/07-updating-data/Final/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/07-updating-data/Final/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/.gitignore b/07-updating-data/Starter/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/07-updating-data/Starter/Bookshelf/.idea/codeStyles/Project.xml b/07-updating-data/Starter/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/07-updating-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/compiler.xml b/07-updating-data/Starter/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/gradle.xml b/07-updating-data/Starter/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/07-updating-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/jarRepositories.xml b/07-updating-data/Starter/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/misc.xml b/07-updating-data/Starter/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/.idea/modules.xml b/07-updating-data/Starter/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/build.gradle b/07-updating-data/Starter/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/google-services.json b/07-updating-data/Starter/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/proguard-rules.pro b/07-updating-data/Starter/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml b/07-updating-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..ea5a312
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // Handle errors
+ if (error != null) {
+ Log.w(TAG, "onEvent:error", error)
+ onError(error)
+ return
+ }
+
+ if (documentSnapshots == null) {
+ return
+ }
+
+ for (change in documentSnapshots.documentChanges) {
+ when (change.type) {
+ DocumentChange.Type.ADDED -> {
+ onDocumentAdded(change)
+ }
+ DocumentChange.Type.MODIFIED -> {
+
+ }
+ DocumentChange.Type.REMOVED -> {
+
+ }
+ }
+ }
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ snapshots.add(change.newIndex, change.document)
+ notifyItemInserted(change.newIndex)
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ // TODO: Implement onDocumentModified
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ if (query != null && registration == null) {
+ registration = query?.addSnapshotListener(this)
+ }
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..258e159
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .orderBy(Book.FIELD_RATING, Query.Direction.DESCENDING)
+ .limit(MainActivity.BOOK_QUERY_LIMIT);
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ // TODO: Implement Update Book
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/values/colors.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/values/strings.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/app/src/main/res/values/styles.xml b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/build.gradle b/07-updating-data/Starter/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/gradle.properties b/07-updating-data/Starter/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/07-updating-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/07-updating-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/07-updating-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/07-updating-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/07-updating-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/07-updating-data/Starter/Bookshelf/gradlew b/07-updating-data/Starter/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/07-updating-data/Starter/Bookshelf/gradlew.bat b/07-updating-data/Starter/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/07-updating-data/Starter/Bookshelf/settings.gradle b/07-updating-data/Starter/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/07-updating-data/Starter/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/.gitignore b/08-deleting-data/Final/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/08-deleting-data/Final/Bookshelf/.idea/codeStyles/Project.xml b/08-deleting-data/Final/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/08-deleting-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/compiler.xml b/08-deleting-data/Final/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/gradle.xml b/08-deleting-data/Final/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/08-deleting-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/jarRepositories.xml b/08-deleting-data/Final/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/misc.xml b/08-deleting-data/Final/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/.idea/modules.xml b/08-deleting-data/Final/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/build.gradle b/08-deleting-data/Final/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/google-services.json b/08-deleting-data/Final/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/proguard-rules.pro b/08-deleting-data/Final/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/AndroidManifest.xml b/08-deleting-data/Final/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..dc649eb
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // Handle errors
+ if (error != null) {
+ Log.w(TAG, "onEvent:error", error)
+ onError(error)
+ return
+ }
+
+ if (documentSnapshots == null) {
+ return
+ }
+
+ for (change in documentSnapshots.documentChanges) {
+ when (change.type) {
+ DocumentChange.Type.ADDED -> {
+ onDocumentAdded(change)
+ }
+ DocumentChange.Type.MODIFIED -> {
+ onDocumentModified(change)
+ }
+ DocumentChange.Type.REMOVED -> {
+ onDocumentRemoved(change)
+ }
+ }
+ }
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ snapshots.add(change.newIndex, change.document)
+ notifyItemInserted(change.newIndex)
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ if (change.oldIndex == change.newIndex) {
+ // Item changed but remained in same position
+ snapshots[change.oldIndex] = change.document
+ notifyItemChanged(change.oldIndex)
+ } else {
+ // Item changed and changed position
+ snapshots.removeAt(change.oldIndex)
+ snapshots.add(change.newIndex, change.document)
+ notifyItemMoved(change.oldIndex, change.newIndex)
+ }
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ snapshots.removeAt(change.oldIndex)
+ notifyItemRemoved(change.oldIndex)
+ }
+
+ fun startListening() {
+ if (query != null && registration == null) {
+ registration = query?.addSnapshotListener(this)
+ }
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..948e3a1
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,24 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ FirebaseFirestore.getInstance()
+ .collection(MainActivity.BOOKS_COLLECTION)
+ .document(adapter.getSnapshot(viewHolder.bindingAdapterPosition).id)
+ .delete()
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..5b956a2
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .orderBy(Book.FIELD_RATING, Query.Direction.DESCENDING)
+ .limit(MainActivity.BOOK_QUERY_LIMIT);
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .document(document.id)
+ .update(Book.FIELD_TITLE, newTitle)
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/values/colors.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/values/strings.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/app/src/main/res/values/styles.xml b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/build.gradle b/08-deleting-data/Final/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/gradle.properties b/08-deleting-data/Final/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/08-deleting-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/08-deleting-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/08-deleting-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/08-deleting-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/08-deleting-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/08-deleting-data/Final/Bookshelf/gradlew b/08-deleting-data/Final/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/08-deleting-data/Final/Bookshelf/gradlew.bat b/08-deleting-data/Final/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/08-deleting-data/Final/Bookshelf/settings.gradle b/08-deleting-data/Final/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/08-deleting-data/Final/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/.gitignore b/08-deleting-data/Starter/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/codeStyles/Project.xml b/08-deleting-data/Starter/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/08-deleting-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/compiler.xml b/08-deleting-data/Starter/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/gradle.xml b/08-deleting-data/Starter/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/08-deleting-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/jarRepositories.xml b/08-deleting-data/Starter/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/misc.xml b/08-deleting-data/Starter/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/.idea/modules.xml b/08-deleting-data/Starter/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/build.gradle b/08-deleting-data/Starter/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/google-services.json b/08-deleting-data/Starter/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/proguard-rules.pro b/08-deleting-data/Starter/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..c618800
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // Handle errors
+ if (error != null) {
+ Log.w(TAG, "onEvent:error", error)
+ onError(error)
+ return
+ }
+
+ if (documentSnapshots == null) {
+ return
+ }
+
+ for (change in documentSnapshots.documentChanges) {
+ when (change.type) {
+ DocumentChange.Type.ADDED -> {
+ onDocumentAdded(change)
+ }
+ DocumentChange.Type.MODIFIED -> {
+ onDocumentModified(change)
+ }
+ DocumentChange.Type.REMOVED -> {
+
+ }
+ }
+ }
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ snapshots.add(change.newIndex, change.document)
+ notifyItemInserted(change.newIndex)
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ if (change.oldIndex == change.newIndex) {
+ // Item changed but remained in same position
+ snapshots[change.oldIndex] = change.document
+ notifyItemChanged(change.oldIndex)
+ } else {
+ // Item changed and changed position
+ snapshots.removeAt(change.oldIndex)
+ snapshots.add(change.newIndex, change.document)
+ notifyItemMoved(change.oldIndex, change.newIndex)
+ }
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ // TODO: Implement onDocumentRemoved
+ }
+
+ fun startListening() {
+ if (query != null && registration == null) {
+ registration = query?.addSnapshotListener(this)
+ }
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..980507d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,21 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ // TODO: Implement onSwiped
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..5b956a2
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .orderBy(Book.FIELD_RATING, Query.Direction.DESCENDING)
+ .limit(MainActivity.BOOK_QUERY_LIMIT);
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .document(document.id)
+ .update(Book.FIELD_TITLE, newTitle)
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/colors.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/strings.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/styles.xml b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/build.gradle b/08-deleting-data/Starter/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/gradle.properties b/08-deleting-data/Starter/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/08-deleting-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/08-deleting-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/08-deleting-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/08-deleting-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/08-deleting-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/08-deleting-data/Starter/Bookshelf/gradlew b/08-deleting-data/Starter/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/08-deleting-data/Starter/Bookshelf/gradlew.bat b/08-deleting-data/Starter/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/08-deleting-data/Starter/Bookshelf/settings.gradle b/08-deleting-data/Starter/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/08-deleting-data/Starter/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/.gitignore b/09-sort-and-filter-data/Final/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/codeStyles/Project.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/compiler.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/gradle.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/jarRepositories.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/misc.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/.idea/modules.xml b/09-sort-and-filter-data/Final/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/build.gradle b/09-sort-and-filter-data/Final/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/google-services.json b/09-sort-and-filter-data/Final/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/proguard-rules.pro b/09-sort-and-filter-data/Final/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/AndroidManifest.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..dc649eb
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // Handle errors
+ if (error != null) {
+ Log.w(TAG, "onEvent:error", error)
+ onError(error)
+ return
+ }
+
+ if (documentSnapshots == null) {
+ return
+ }
+
+ for (change in documentSnapshots.documentChanges) {
+ when (change.type) {
+ DocumentChange.Type.ADDED -> {
+ onDocumentAdded(change)
+ }
+ DocumentChange.Type.MODIFIED -> {
+ onDocumentModified(change)
+ }
+ DocumentChange.Type.REMOVED -> {
+ onDocumentRemoved(change)
+ }
+ }
+ }
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ snapshots.add(change.newIndex, change.document)
+ notifyItemInserted(change.newIndex)
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ if (change.oldIndex == change.newIndex) {
+ // Item changed but remained in same position
+ snapshots[change.oldIndex] = change.document
+ notifyItemChanged(change.oldIndex)
+ } else {
+ // Item changed and changed position
+ snapshots.removeAt(change.oldIndex)
+ snapshots.add(change.newIndex, change.document)
+ notifyItemMoved(change.oldIndex, change.newIndex)
+ }
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ snapshots.removeAt(change.oldIndex)
+ notifyItemRemoved(change.oldIndex)
+ }
+
+ fun startListening() {
+ if (query != null && registration == null) {
+ registration = query?.addSnapshotListener(this)
+ }
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..948e3a1
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,24 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ FirebaseFirestore.getInstance()
+ .collection(MainActivity.BOOKS_COLLECTION)
+ .document(adapter.getSnapshot(viewHolder.bindingAdapterPosition).id)
+ .delete()
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..797849e
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .orderBy(Book.FIELD_RATING, Query.Direction.DESCENDING)
+ .limit(MainActivity.BOOK_QUERY_LIMIT);
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .document(document.id)
+ .update(Book.FIELD_TITLE, newTitle)
+ }
+
+ fun prepareQuery(filters: Filters) {
+ var query: Query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ if (filters.category != null) {
+ query = query.whereEqualTo(Book.FIELD_CATEGORY, filters.category)
+ }
+
+ if (filters.author != null) {
+ query = query.whereEqualTo(Book.FIELD_AUTHOR, filters.author)
+ }
+
+ if (filters.sortBy != null && filters.sortDirection != null) {
+ query = query.orderBy(filters.sortBy, filters.sortDirection)
+ }
+
+ this.query = query.limit(MainActivity.BOOK_QUERY_LIMIT)
+ this.filters = filters
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/colors.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/strings.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/styles.xml b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/build.gradle b/09-sort-and-filter-data/Final/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/gradle.properties b/09-sort-and-filter-data/Final/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/09-sort-and-filter-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/09-sort-and-filter-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/09-sort-and-filter-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/09-sort-and-filter-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/09-sort-and-filter-data/Final/Bookshelf/gradlew b/09-sort-and-filter-data/Final/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/09-sort-and-filter-data/Final/Bookshelf/gradlew.bat b/09-sort-and-filter-data/Final/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/09-sort-and-filter-data/Final/Bookshelf/settings.gradle b/09-sort-and-filter-data/Final/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/09-sort-and-filter-data/Final/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/.gitignore b/09-sort-and-filter-data/Starter/Bookshelf/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/codeStyles/Project.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1c5d108
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/codeStyles/Project.xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..38a6942
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/compiler.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/gradle.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/gradle.xml
new file mode 100644
index 0000000..cc2be69
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/gradle.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cac2c1a
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,922 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/jarRepositories.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
new file mode 100644
index 0000000..ed5c5d6
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
new file mode 100644
index 0000000..3c1b815
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_activity_activity_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
new file mode 100644
index 0000000..b2158ac
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
new file mode 100644
index 0000000..2bcc663
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
new file mode 100644
index 0000000..c6767dc
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
new file mode 100644
index 0000000..43e5bc7
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
new file mode 100644
index 0000000..2208415
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
new file mode 100644
index 0000000..f459d10
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..62f576c
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
new file mode 100644
index 0000000..c990088
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_browser_browser_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
new file mode 100644
index 0000000..8e7a89d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cardview_cardview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
new file mode 100644
index 0000000..eafc05e
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
new file mode 100644
index 0000000..78445b7
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_1_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
new file mode 100644
index 0000000..3a9b971
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_2_0_4_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
new file mode 100644
index 0000000..24d3804
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_1.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
new file mode 100644
index 0000000..cba1dae
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_constraintlayout_constraintlayout_solver_2_0_4.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
new file mode 100644
index 0000000..1555070
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
new file mode 100644
index 0000000..34ed74c
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
new file mode 100644
index 0000000..ce972b4
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
new file mode 100644
index 0000000..eccf948
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
new file mode 100644
index 0000000..045335a
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_databinding_viewbinding_4_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
new file mode 100644
index 0000000..1b68b48
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_documentfile_documentfile_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
new file mode 100644
index 0000000..e53ce03
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
new file mode 100644
index 0000000..5230c0e
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_dynamicanimation_dynamicanimation_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
new file mode 100644
index 0000000..9ba64f1
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
new file mode 100644
index 0000000..a73b36b
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
new file mode 100644
index 0000000..89a2e91
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_fragment_fragment_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
new file mode 100644
index 0000000..ada17c7
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
new file mode 100644
index 0000000..e439ff6
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_legacy_legacy_support_core_utils_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
new file mode 100644
index 0000000..9354d44
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
new file mode 100644
index 0000000..f7d6479
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
new file mode 100644
index 0000000..dfcc5cc
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
new file mode 100644
index 0000000..0b127d8
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_extensions_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
new file mode 100644
index 0000000..88250ba
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
new file mode 100644
index 0000000..0fa0362
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
new file mode 100644
index 0000000..94ba833
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
new file mode 100644
index 0000000..9c3f12f
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
new file mode 100644
index 0000000..c93159a
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
new file mode 100644
index 0000000..3497db9
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_process_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
new file mode 100644
index 0000000..b7be403
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
new file mode 100644
index 0000000..b5338f0
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_0_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
new file mode 100644
index 0000000..2637988
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_service_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
new file mode 100644
index 0000000..b48a501
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
new file mode 100644
index 0000000..1ca96ab
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_2_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..50c3ea2
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
new file mode 100644
index 0000000..0d4075d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
new file mode 100644
index 0000000..9860348
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_localbroadcastmanager_localbroadcastmanager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
new file mode 100644
index 0000000..698288c
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_print_print_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
new file mode 100644
index 0000000..7ec2bbc
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_recyclerview_recyclerview_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
new file mode 100644
index 0000000..ee8739b
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
new file mode 100644
index 0000000..3c883e8
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_transition_transition_1_2_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
new file mode 100644
index 0000000..54a8af2
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
new file mode 100644
index 0000000..eee73d4
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
new file mode 100644
index 0000000..b3b9b50
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
new file mode 100644
index 0000000..914b959
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager2_viewpager2_1_0_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
new file mode 100644
index 0000000..56d8a5d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
new file mode 100644
index 0000000..3813317
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_firebaseui_firebase_ui_auth_7_1_1_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
new file mode 100644
index 0000000..bb28a4b
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
new file mode 100644
index 0000000..89573e4
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
new file mode 100644
index 0000000..e53f55b
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_12_0_aar.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
new file mode 100644
index 0000000..080a3b0
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_12_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
new file mode 100644
index 0000000..1703605
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_19_0_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
new file mode 100644
index 0000000..8ceb90f
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_api_phone_17_4_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
new file mode 100644
index 0000000..5c5c3ee
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_auth_base_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
new file mode 100644
index 0000000..b41e91e
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_base_17_1_0_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
new file mode 100644
index 0000000..7953a9b
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_basement_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
new file mode 100644
index 0000000..22625b4
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_safetynet_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
new file mode 100644
index 0000000..242af02
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_gms_play_services_tasks_17_0_0_aar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
new file mode 100644
index 0000000..319f0b5
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_android_material_material_1_3_0_aar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 0000000..a96d725
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
new file mode 100644
index 0000000..0d56cda
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_annotations_16_0_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
new file mode 100644
index 0000000..765d7e1
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_20_0_4_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
new file mode 100644
index 0000000..ff1620f
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_auth_interop_19_0_2_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
new file mode 100644
index 0000000..a03f0e2
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_common_19_5_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
new file mode 100644
index 0000000..f300392
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_components_16_1_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
new file mode 100644
index 0000000..2bcd120
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_database_collection_17_0_1_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
new file mode 100644
index 0000000..b75bd20
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_firebase_firestore_22_1_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
new file mode 100644
index 0000000..0375448
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_firebase_protolite_well_known_types_17_1_1_aar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
new file mode 100644
index 0000000..aeb2fc7
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
new file mode 100644
index 0000000..703e775
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_28_1_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
new file mode 100644
index 0000000..f561112
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_guava_29_0_android.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
new file mode 100644
index 0000000..11f8cce
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
new file mode 100644
index 0000000..7a61cf9
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
new file mode 100644
index 0000000..52b2a18
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_google_protobuf_protobuf_javalite_3_14_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
new file mode 100644
index 0000000..980c165
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okhttp_okhttp_2_7_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
new file mode 100644
index 0000000..913412c
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
new file mode 100644
index 0000000..ca6737d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__com_squareup_okio_okio_1_6_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
new file mode 100644
index 0000000..9c4f6f1
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_android_1_28_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
new file mode 100644
index 0000000..11b8f0e
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_api_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
new file mode 100644
index 0000000..6ce32db
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_context_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
new file mode 100644
index 0000000..bd8666d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_core_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
new file mode 100644
index 0000000..b850c21
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_okhttp_1_32_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
new file mode 100644
index 0000000..3f12f22
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
new file mode 100644
index 0000000..eb084c0
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_grpc_grpc_stub_1_28_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
new file mode 100644
index 0000000..8380845
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_2_2_2_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
new file mode 100644
index 0000000..d18c603
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_scope_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
new file mode 100644
index 0000000..2288c77
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_android_viewmodel_2_2_2_aar.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
new file mode 100644
index 0000000..484e595
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__io_insert_koin_koin_core_2_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
new file mode 100644
index 0000000..c2e589f
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__me_zhanghai_android_materialratingbar_library_1_4_0_aar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
new file mode 100644
index 0000000..b511655
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_checkerframework_checker_compat_qual_2_5_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
new file mode 100644
index 0000000..1fa0fa9
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
new file mode 100644
index 0000000..88964ea
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
new file mode 100644
index 0000000..b8fb474
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
new file mode 100644
index 0000000..b3dbffe
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
new file mode 100644
index 0000000..83db867
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk8_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/misc.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/misc.xml
new file mode 100644
index 0000000..395ca04
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/.idea/modules.xml b/09-sort-and-filter-data/Starter/Bookshelf/.idea/modules.xml
new file mode 100644
index 0000000..e01cde6
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/build.gradle b/09-sort-and-filter-data/Starter/Bookshelf/app/build.gradle
new file mode 100644
index 0000000..46293ea
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.raywenderlich.android.bookshelf"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ // Support Libs
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'androidx.browser:browser:1.3.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0'
+ implementation "io.grpc:grpc-okhttp:1.32.2"
+
+ // Other Firebase/Play services deps
+ implementation 'com.google.firebase:firebase-auth:20.0.4'
+ implementation 'com.google.android.gms:play-services-auth:19.0.0'
+
+ // Third-party libraries
+ implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation "io.insert-koin:koin-android-viewmodel:2.2.2"
+
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:22.1.2'
+
+ // FirebaseUI (for authentication)
+ implementation 'com.firebaseui:firebase-ui-auth:7.1.1'
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/google-services.json b/09-sort-and-filter-data/Starter/Bookshelf/app/google-services.json
new file mode 100644
index 0000000..315e884
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/google-services.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "483799781579",
+ "project_id": "bookshelf-c6dc6",
+ "storage_bucket": "bookshelf-c6dc6.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:483799781579:android:a6667fc68d80321893cb4e",
+ "android_client_info": {
+ "package_name": "com.raywenderlich.android.bookshelf"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "483799781579-0rom8kb2vkhmlrqr8hnukdc7ole7ob1r.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.raywenderlich.android.bookshelf",
+ "certificate_hash": "ae287ce0750830d54343dc5c343e7c30a272212e"
+ }
+ },
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDTBDZewM_Q9H4zdK46E3on8n7vxzLCUU"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "483799781579-b15j5e70bfu4fkuu9cfd9ej46e663u8t.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/proguard-rules.pro b/09-sort-and-filter-data/Starter/Bookshelf/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea15cdb
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
new file mode 100644
index 0000000..ee06576
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/BookshelfApplication.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf
+
+import android.app.Application
+import com.raywenderlich.android.bookshelf.di.app
+import com.raywenderlich.android.bookshelf.di.viewModels
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class BookshelfApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ startKoin {
+ androidContext(this@BookshelfApplication)
+ modules(
+ app,
+ viewModels
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
new file mode 100644
index 0000000..c53c551
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/di/KoinModules.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.di
+
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainViewModel
+import org.koin.android.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val app = module {
+ single { FirebaseFirestore.getInstance() }
+}
+
+val viewModels = module {
+ viewModel { MainViewModel(fireStore = get()) }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
new file mode 100644
index 0000000..dba6d65
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Book.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+data class Book(
+ val title: String = "",
+ val author: String = "",
+ val category: String = "",
+ val rating: Float = 0f,
+ val coverArt: String = "",
+ val yearPublished: Int = 0
+) {
+ companion object {
+ const val FIELD_TITLE = "title"
+ const val FIELD_AUTHOR = "author"
+ const val FIELD_CATEGORY = "category"
+ const val FIELD_RATING = "rating"
+ const val FIELD_COVER_ART = "coverArt"
+ const val FIELD_YEAR_PUBLISHED = "yearPublished"
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
new file mode 100644
index 0000000..9666cce
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/BookUtil.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import java.util.*
+
+class BookUtil {
+ private val imagesRootUrl =
+ "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/"
+
+ private val books = listOf(
+ Book(
+ "Crime and Punishment",
+ "Fyodor Dostoevsky",
+ "Classics",
+ 3.23f,
+ "${imagesRootUrl}1382846449l/7144.jpg",
+ 2017
+ ),
+ Book(
+ "Think and Grow Rich",
+ "Napoleon Hill",
+ "Business",
+ 5.17f,
+ "${imagesRootUrl}1392024158l/815412.jpg",
+ 1992
+ ),
+ Book(
+ "Hackers and Painters",
+ "Paul Graham",
+ "Nonfiction",
+ 3.06f,
+ "${imagesRootUrl}1387653624l/6565257.jpg",
+ 1997
+ ),
+ Book(
+ "Fight Club",
+ "Chuck Palahniuk",
+ "Fiction",
+ 3.18f,
+ "${imagesRootUrl}1327866366l/825840.jpg",
+ 1989
+ ),
+ Book(
+ "Masters of Doom",
+ "David Kushner",
+ "Nonfiction",
+ 2.28f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 2009
+ ),
+ Book(
+ "1984",
+ "George Orwell",
+ "Classics",
+ 1.19f,
+ "${imagesRootUrl}1557932856l/222146._SY475_.jpg",
+ 1993
+ ),
+ Book(
+ "Fathers and Sons",
+ "Ivan Turgenev",
+ "Classics",
+ 4.96f,
+ "${imagesRootUrl}1388798930l/373813.jpg",
+ 2012
+ ),
+ Book(
+ "Hackers: Heroes of the Computer Revolution",
+ "Steven Levy",
+ "Nonfiction",
+ 2.15f,
+ "${imagesRootUrl}1413406427l/1416856.jpg",
+ 1977
+ ),
+ Book(
+ "The Prince",
+ "Niccolo Machiavelli",
+ "Classics",
+ 3.82f,
+ "${imagesRootUrl}1390055828l/28862.jpg",
+ 2020
+ ),
+ Book(
+ "How to Win Friends and Influence People",
+ "Dale Carnegie",
+ "Nonfiction",
+ 4.21f,
+ "${imagesRootUrl}1442726934l/4865._SY475_.jpg",
+ 1996
+ ),
+ Book(
+ "The Clean Coder",
+ "Robert Martin",
+ "Computer Science",
+ 4.28f,
+ "${imagesRootUrl}1347470803l/10284614.jpg",
+ 1995
+ ),
+ Book(
+ "Clean Code",
+ "Robert Martin",
+ "Computer Science",
+ 4.40f,
+ "${imagesRootUrl}1436202607l/3735293._SX318_.jpg",
+ 2005
+ ),
+ Book(
+ "The Alchemist",
+ "Paulo Coelho",
+ "Fiction",
+ 1.88f,
+ "${imagesRootUrl}1483412266l/865.jpg",
+ 2002
+ ),
+ Book(
+ "The Epic of Gilgamesh",
+ "Anonymous",
+ "Classics",
+ 5.70f,
+ "${imagesRootUrl}1370840401l/19350.jpg",
+ 2009
+ ),
+ Book(
+ "The Fall",
+ "Albert Camus",
+ "Fiction",
+ 3.02f,
+ "${imagesRootUrl}1439035433l/219972._SY475_.jpg",
+ 2014
+ ),
+ Book(
+ "Waiting for Godot",
+ "Samuel Beckett",
+ "Plays",
+ 1.83f,
+ "${imagesRootUrl}1458410754l/772273._SY475_.jpg",
+ 2013
+ ),
+ Book(
+ "The Prophet",
+ "Khalil Gebran",
+ "Poetry",
+ 5.22f,
+ "${imagesRootUrl}1355046521l/2547.jpg",
+ 2014
+ ),
+ Book(
+ "The Plague",
+ "Albert Camus",
+ "Fiction",
+ 5.01f,
+ "${imagesRootUrl}1503362434l/11989._SY475_.jpg",
+ 1999
+ ),
+ Book(
+ "The Birth of Tragedy",
+ "Frederich Nietzsche",
+ "Philosophy",
+ 1.98f,
+ "${imagesRootUrl}1429743385l/2823.jpg",
+ 1999
+ ),
+ Book(
+ "Brave New World",
+ "Aldous Huxley",
+ "Classics",
+ 4.99f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2000
+ ),
+ Book(
+ "The Great Gatsby",
+ "F. Scott FitzGerald",
+ "Classics",
+ 3.93f,
+ "${imagesRootUrl}1565335374l/996156._SY475_.jpg",
+ 2007
+ ),
+
+ Book(
+ "What Comes After",
+ "Joanne Tompkins",
+ "Classics",
+ 3.07f,
+ "${imagesRootUrl}1597695077l/54610962.jpg",
+ 1981
+ ),
+ Book(
+ "Too Good To Be True",
+ "Carola Lovering",
+ "Thriller",
+ 2.88f,
+ "${imagesRootUrl}1607321994l/53137955.jpg",
+ 1983
+ ),
+ Book(
+ "The Hunting Wives",
+ "May Cobb",
+ "Thriller",
+ 2.75f,
+ "${imagesRootUrl}1601598187l/45714854.jpg",
+ 1987
+ ),
+ Book(
+ "Empire of Pain",
+ "Patrick Keefe",
+ "Nonfiction",
+ 2.72f,
+ "${imagesRootUrl}1611952534l/43868109.jpg",
+ 2001
+ ),
+ Book(
+ "Code Complete",
+ "Steve McConnell",
+ "Computer Science",
+ 5.03f,
+ "${imagesRootUrl}1396837641l/4845.jpg",
+ 2001
+ ),
+ Book(
+ "Head First Design Patterns",
+ "Eric Freeman",
+ "Computer Science",
+ 5.28f,
+ "${imagesRootUrl}1408309444l/58128.jpg",
+ 1992
+ ),
+ Book(
+ "Effective Java",
+ "Joshua Bloch",
+ "Computer Science",
+ 1.51f,
+ "${imagesRootUrl}1513389229l/34927404.jpg",
+ 1995
+ ),
+ Book(
+ "Javascript: The Good Parts",
+ "Douglas Crockford",
+ "Computer Science",
+ 2.23f,
+ "${imagesRootUrl}1328834793l/2998152.jpg",
+ 2019
+ ),
+ Book(
+ "The C Programming Language",
+ "Dennis Ritchie, Brian Kernighan",
+ "Computer Science",
+ 1.5f,
+ "${imagesRootUrl}1391032531l/515601.jpg",
+ 1994
+ ),
+ )
+
+ fun getRandom(): Book {
+ return books[Random().nextInt(books.size)]
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
new file mode 100644
index 0000000..1c0e05a
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/model/Filters.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.model
+
+import android.content.Context
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+
+class Filters(
+ val category: String? = null,
+ val author: String? = null,
+ val sortBy: String? = null,
+ val sortDirection: Query.Direction? = null
+) {
+
+ fun getSearchDescription(context: Context): String {
+ val desc = StringBuilder()
+ if (category == null && author == null) {
+ desc.append("")
+ desc.append(context.getString(R.string.all_books))
+ desc.append("")
+ }
+ if (author != null) {
+ desc.append("")
+ desc.append(author)
+ desc.append("")
+ }
+ if (category != null && author != null) {
+ desc.append(" in ")
+ }
+ if (category != null) {
+ desc.append("")
+ desc.append(category)
+ desc.append("")
+ }
+ return desc.toString()
+ }
+
+ fun getOrderDescription(context: Context): String {
+ return when (sortBy) {
+ Book.FIELD_RATING -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ Book.FIELD_TITLE -> {
+ context.getString(R.string.sorted_alphabetically)
+ }
+ Book.FIELD_YEAR_PUBLISHED -> {
+ context.getString(R.string.sorted_by_year)
+ }
+ else -> {
+ context.getString(R.string.sorted_by_rating)
+ }
+ }
+ }
+
+ companion object {
+ val default: Filters
+ get() {
+ return Filters(
+ sortBy = Book.FIELD_RATING,
+ sortDirection = Query.Direction.DESCENDING
+ )
+ }
+ }
+}
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
new file mode 100644
index 0000000..9453c70
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/BooksAdapter.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import me.zhanghai.android.materialratingbar.MaterialRatingBar
+
+open class BooksAdapter(
+ query: Query?,
+ private val onClickListener: (String, DocumentSnapshot) -> Unit
+) : FirestoreAdapter(query) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return ViewHolder(inflater.inflate(R.layout.item_book, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getSnapshot(position), onClickListener)
+ }
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private var imageView: ImageView = itemView.findViewById(R.id.book_item_image)
+ private var titleView: TextView = itemView.findViewById(R.id.book_item_title)
+ private var authorView: TextView = itemView.findViewById(R.id.book_item_author)
+ private var yearView: TextView = itemView.findViewById(R.id.book_item_year_published)
+ private var categoryView: TextView = itemView.findViewById(R.id.book_item_category)
+ private var ratingBar: MaterialRatingBar = itemView.findViewById(R.id.book_item_rating)
+
+ fun bind(snapshot: DocumentSnapshot, onClickListener: (String, DocumentSnapshot) -> Unit) {
+ val book: Book? = snapshot.toObject(Book::class.java)
+
+ if (book != null) {
+ Glide.with(imageView.context)
+ .load(book.coverArt)
+ .into(imageView)
+
+ titleView.text = book.title
+
+ authorView.text = book.author
+
+ ratingBar.rating = book.rating
+
+ categoryView.text = book.category
+
+ yearView.text = book.yearPublished.toString()
+
+ itemView.setOnClickListener {
+ onClickListener(book.title, snapshot)
+ }
+ }
+ }
+ }
+}
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
new file mode 100644
index 0000000..dc649eb
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/FirestoreAdapter.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import android.util.Log
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.*
+import com.google.firebase.firestore.EventListener
+import java.util.*
+
+abstract class FirestoreAdapter(
+ private var query: Query?
+) : RecyclerView.Adapter(), EventListener {
+
+ private var registration: ListenerRegistration? = null
+ private val snapshots = ArrayList()
+
+ open fun onDataChanged() {}
+ open fun onError(e: FirebaseFirestoreException) {}
+
+ override fun getItemCount(): Int {
+ return snapshots.size
+ }
+
+ override fun onEvent(documentSnapshots: QuerySnapshot?, error: FirebaseFirestoreException?) {
+ // Handle errors
+ if (error != null) {
+ Log.w(TAG, "onEvent:error", error)
+ onError(error)
+ return
+ }
+
+ if (documentSnapshots == null) {
+ return
+ }
+
+ for (change in documentSnapshots.documentChanges) {
+ when (change.type) {
+ DocumentChange.Type.ADDED -> {
+ onDocumentAdded(change)
+ }
+ DocumentChange.Type.MODIFIED -> {
+ onDocumentModified(change)
+ }
+ DocumentChange.Type.REMOVED -> {
+ onDocumentRemoved(change)
+ }
+ }
+ }
+ }
+
+ fun setQuery(query: Query?) {
+ // Stop listening
+ stopListening()
+
+ // Clear existing data
+ snapshots.clear()
+ notifyDataSetChanged()
+
+ // Listen to new query
+ this.query = query
+
+ startListening()
+ }
+
+ fun getSnapshot(index: Int): DocumentSnapshot {
+ return snapshots[index]
+ }
+
+ private fun onDocumentAdded(change: DocumentChange) {
+ snapshots.add(change.newIndex, change.document)
+ notifyItemInserted(change.newIndex)
+ }
+
+ private fun onDocumentModified(change: DocumentChange) {
+ if (change.oldIndex == change.newIndex) {
+ // Item changed but remained in same position
+ snapshots[change.oldIndex] = change.document
+ notifyItemChanged(change.oldIndex)
+ } else {
+ // Item changed and changed position
+ snapshots.removeAt(change.oldIndex)
+ snapshots.add(change.newIndex, change.document)
+ notifyItemMoved(change.oldIndex, change.newIndex)
+ }
+ }
+
+ private fun onDocumentRemoved(change: DocumentChange) {
+ snapshots.removeAt(change.oldIndex)
+ notifyItemRemoved(change.oldIndex)
+ }
+
+ fun startListening() {
+ if (query != null && registration == null) {
+ registration = query?.addSnapshotListener(this)
+ }
+ }
+
+ fun stopListening() {
+ registration?.remove()
+ registration = null
+
+ snapshots.clear()
+ notifyDataSetChanged()
+ }
+
+ companion object {
+ private const val TAG = "Firestore Adapter"
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
new file mode 100644
index 0000000..948e3a1
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/adapters/SwipeToDeleteCallback.kt
@@ -0,0 +1,24 @@
+package com.raywenderlich.android.bookshelf.ui.adapters
+
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.google.firebase.firestore.FirebaseFirestore
+import com.raywenderlich.android.bookshelf.ui.main.MainActivity
+
+class SwipeToDeleteCallback(
+ private val adapter: BooksAdapter
+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = false
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ FirebaseFirestore.getInstance()
+ .collection(MainActivity.BOOKS_COLLECTION)
+ .document(adapter.getSnapshot(viewHolder.bindingAdapterPosition).id)
+ .delete()
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
new file mode 100644
index 0000000..e9b1b53
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/FilterDialogFragment.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Spinner
+import androidx.fragment.app.DialogFragment
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class FilterDialogFragment : DialogFragment(), View.OnClickListener {
+
+ interface FilterListener {
+ fun onFilter(filters: Filters)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var authorSpinner: Spinner
+ private lateinit var categorySpinner: Spinner
+ private lateinit var sortSpinner: Spinner
+ private lateinit var filterListener: FilterListener
+
+ private val filters: Filters
+ get() {
+ return Filters(
+ selectedCategory,
+ selectedAuthor,
+ selectedSortBy,
+ sortDirection
+ )
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_filters, container, false)
+ categorySpinner = rootView.findViewById(R.id.spinner_category)
+ authorSpinner = rootView.findViewById(R.id.spinner_author)
+ sortSpinner = rootView.findViewById(R.id.spinner_sort)
+ rootView.findViewById(R.id.button_apply).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ return rootView
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is FilterListener) {
+ filterListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_apply -> onApplyClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onApplyClicked() {
+ filterListener.onFilter(filters)
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ fun resetFilters() {
+ categorySpinner.setSelection(0)
+ authorSpinner.setSelection(0)
+ sortSpinner.setSelection(0)
+ }
+
+ private val selectedCategory: String?
+ get() {
+ val selected = categorySpinner.selectedItem as String
+ return if (getString(R.string.value_any_category) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedAuthor: String?
+ get() {
+ val selected = authorSpinner.selectedItem as String
+ return if (getString(R.string.value_any_author) == selected) {
+ null
+ } else {
+ selected
+ }
+ }
+
+ private val selectedSortBy: String?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Book.FIELD_RATING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Book.FIELD_YEAR_PUBLISHED
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Book.FIELD_TITLE
+ } else null
+ }
+
+ private val sortDirection: Query.Direction?
+ get() {
+ val selected = sortSpinner.selectedItem as String
+ if (getString(R.string.sort_by_rating) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ if (getString(R.string.sort_by_year) == selected) {
+ return Query.Direction.DESCENDING
+ }
+ return if (getString(R.string.sort_alphabetically) == selected) {
+ Query.Direction.ASCENDING
+ } else null
+ }
+
+ companion object {
+ const val TAG = "FilterDialog"
+ }
+}
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
new file mode 100644
index 0000000..ef424e8
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/dialogs/UpdateBookDialogFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.fragment.app.DialogFragment
+import com.raywenderlich.android.bookshelf.R
+
+class UpdateBookDialogFragment(private val currentTitle: String) : DialogFragment(),
+ View.OnClickListener {
+
+ interface UpdateBookListener {
+ fun onBookTitleUpdate(newTitle: String)
+ }
+
+ private lateinit var rootView: View
+ private lateinit var bookNameInput: EditText
+
+ private lateinit var updateBookListener: UpdateBookListener
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ rootView = inflater.inflate(R.layout.dialog_update_book, container, false)
+ rootView.findViewById(R.id.button_update).setOnClickListener(this)
+ rootView.findViewById(R.id.button_cancel).setOnClickListener(this)
+ bookNameInput = rootView.findViewById(R.id.book_name_input)
+ return rootView
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ bookNameInput.setText(currentTitle)
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ if (context is UpdateBookListener) {
+ updateBookListener = context
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog!!.window!!.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_update -> onUpdateClicked()
+ R.id.button_cancel -> onCancelClicked()
+ }
+ }
+
+ private fun onUpdateClicked() {
+ updateBookListener.onBookTitleUpdate(bookNameInput.text.toString())
+ dismiss()
+ }
+
+ private fun onCancelClicked() {
+ dismiss()
+ }
+
+ companion object {
+ const val TAG = "UpdateBookDialog"
+ }
+}
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
new file mode 100644
index 0000000..1276521
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainActivity.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.text.HtmlCompat
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.firestore.*
+import com.raywenderlich.android.bookshelf.R
+import com.raywenderlich.android.bookshelf.databinding.ActivityMainBinding
+import com.raywenderlich.android.bookshelf.model.Filters
+import com.raywenderlich.android.bookshelf.ui.adapters.BooksAdapter
+import com.raywenderlich.android.bookshelf.ui.adapters.SwipeToDeleteCallback
+import com.raywenderlich.android.bookshelf.ui.dialogs.FilterDialogFragment
+import com.raywenderlich.android.bookshelf.ui.dialogs.UpdateBookDialogFragment
+import org.koin.android.viewmodel.ext.android.viewModel
+
+class MainActivity : AppCompatActivity(),
+ FilterDialogFragment.FilterListener, UpdateBookDialogFragment.UpdateBookListener,
+ View.OnClickListener {
+
+ private lateinit var binding: ActivityMainBinding
+
+ private lateinit var booksAdapter: BooksAdapter
+
+ private val filterDialog = FilterDialogFragment()
+ private lateinit var updateBookDialog : UpdateBookDialogFragment
+
+ private val viewModel: MainViewModel by viewModel()
+
+ private lateinit var documentClicked: DocumentSnapshot
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.toolbar)
+
+ binding.filterBar.setOnClickListener(this)
+ binding.buttonClearFilter.setOnClickListener(this)
+ binding.addBooksFab.setOnClickListener(this)
+
+ initRecyclerView()
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ onFilter(viewModel.filters)
+
+ booksAdapter.startListening()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ booksAdapter.stopListening()
+ }
+
+ private fun initRecyclerView() {
+ val onBookClicked = object : (String, DocumentSnapshot) -> Unit {
+ override fun invoke(currentTitle: String, document: DocumentSnapshot) {
+ updateBookDialog = UpdateBookDialogFragment(currentTitle)
+
+ documentClicked = document
+
+ updateBookDialog.show(supportFragmentManager, UpdateBookDialogFragment.TAG)
+ }
+ }
+
+ with(binding) {
+ booksAdapter = object : BooksAdapter(viewModel.query, onBookClicked) {
+ override fun onDataChanged() {
+ if (itemCount == 0) {
+ booksRecycler.visibility = View.GONE
+ emptyView.visibility = View.VISIBLE
+ } else {
+ booksRecycler.visibility = View.VISIBLE
+ emptyView.visibility = View.GONE
+ }
+ }
+
+ override fun onError(e: FirebaseFirestoreException) {
+ emptyView.visibility = View.GONE
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Error: ${e.localizedMessage}", Snackbar.LENGTH_LONG
+ ).show()
+ }
+ }
+ booksRecycler.layoutManager = LinearLayoutManager(this@MainActivity)
+ booksRecycler.adapter = booksAdapter
+ val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(booksAdapter))
+ itemTouchHelper.attachToRecyclerView(booksRecycler)
+ }
+ }
+
+ override fun onClick(view: View) {
+ when (view.id) {
+ R.id.add_books_fab -> {
+ if (binding.addBooksFab.isExtended) {
+ binding.addBooksFab.shrink()
+
+ viewModel.addBooksClicked()
+ } else {
+ binding.addBooksFab.extend()
+ }
+ }
+ R.id.filter_bar -> {
+ onFilterClicked()
+ }
+ R.id.button_clear_filter -> {
+ onClearFilterClicked()
+ }
+ }
+ }
+
+ override fun onBookTitleUpdate(newTitle: String) {
+ viewModel.updateBook(documentClicked, newTitle)
+ }
+
+ override fun onFilter(filters: Filters) {
+ viewModel.prepareQuery(filters)
+
+ booksAdapter.setQuery(viewModel.query)
+
+ binding.textCurrentSearch.text = HtmlCompat.fromHtml(
+ filters.getSearchDescription(this),
+ HtmlCompat.FROM_HTML_MODE_COMPACT
+ )
+
+ binding.textCurrentSortBy.text = filters.getOrderDescription(this)
+ }
+
+ private fun onFilterClicked() {
+ filterDialog.show(supportFragmentManager, FilterDialogFragment.TAG)
+ }
+
+ private fun onClearFilterClicked() {
+ filterDialog.resetFilters()
+ onFilter(Filters.default)
+ }
+
+ companion object {
+ private const val TAG = "MainActivity"
+ private const val RC_SIGN_IN = 9001
+ const val BOOKS_COLLECTION = "books"
+ const val BOOK_QUERY_LIMIT: Long = 30
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
new file mode 100644
index 0000000..5b956a2
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/java/com/raywenderlich/android/bookshelf/ui/main/MainViewModel.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021 Razeware LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
+ * distribute, sublicense, create a derivative work, and/or sell copies of the
+ * Software in any work that is designed, intended, or marketed for pedagogical or
+ * instructional purposes related to programming, coding, application development,
+ * or information technology. Permission for such use, copying, modification,
+ * merger, publication, distribution, sublicensing, creation of derivative works,
+ * or sale is expressly withheld.
+ *
+ * This project and source code may use libraries or frameworks that are
+ * released under various Open-Source licenses. Use of those libraries and
+ * frameworks are governed by their own individual licenses.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.raywenderlich.android.bookshelf.ui.main
+
+import androidx.lifecycle.ViewModel
+import com.google.firebase.firestore.CollectionReference
+import com.google.firebase.firestore.DocumentSnapshot
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.raywenderlich.android.bookshelf.model.Book
+import com.raywenderlich.android.bookshelf.model.BookUtil
+import com.raywenderlich.android.bookshelf.model.Filters
+
+class MainViewModel(private val fireStore: FirebaseFirestore) : ViewModel() {
+
+ var filters: Filters = Filters.default
+
+ var query: Query? = null
+
+ val books: CollectionReference = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+
+ val prevBooks = mutableListOf()
+
+ init {
+ query = fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .orderBy(Book.FIELD_RATING, Query.Direction.DESCENDING)
+ .limit(MainActivity.BOOK_QUERY_LIMIT);
+ }
+
+ fun addBooksClicked() {
+ var book: Book
+
+ for (i in 0..15) {
+ book = BookUtil().getRandom()
+
+ if (!prevBooks.contains(book)) {
+ books.add(book)
+ }
+
+ prevBooks.add(book)
+ }
+ }
+
+ fun updateBook(document: DocumentSnapshot, newTitle: String) {
+ fireStore.collection(MainActivity.BOOKS_COLLECTION)
+ .document(document.id)
+ .update(Book.FIELD_TITLE, newTitle)
+ }
+
+ fun prepareQuery(filters: Filters) {
+ // TODO: Implement how the query is constructed
+ }
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png
new file mode 100644
index 0000000..212b67f
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable-nodpi/book_kid.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
new file mode 100644
index 0000000..09a2923
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_close_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
new file mode 100644
index 0000000..352dbbc
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_filter_list_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..c975946
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
new file mode 100644
index 0000000..ef4b2b1
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_author_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
new file mode 100644
index 0000000..91e3d9f
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_auto_stories_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
new file mode 100644
index 0000000..7950c77
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_category_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
new file mode 100644
index 0000000..195778b
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_outline_menu_book_24.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
new file mode 100644
index 0000000..7cc48ad
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/ic_sort_white_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
new file mode 100644
index 0000000..76d357d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/drawable/outline_book_add_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..830583e
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
new file mode 100644
index 0000000..15627ac
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/dialog_filters.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
new file mode 100644
index 0000000..07ed847
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/dialog_update_book.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..ace5682
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..501c692
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0051052
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..3aa59f3
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1f963a5
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bdef4c5
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ed48b5c
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..de51139
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..00ee22d
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..758ad04
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..45528f1
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c262547
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..174413e
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ef45a96
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f58ab70
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d1a1120
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b7cad06
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/colors.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..be485c8
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #4285F4
+ #3367D6
+ #F4B400
+
+ #DE000000
+ #8B000000
+ #61000000
+
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..9bc5213
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/strings.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3114c65
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/strings.xml
@@ -0,0 +1,81 @@
+
+ Bookshelf
+
+ Cancel
+ Apply
+ Update
+ •
+
+ Add Books
+
+ Oops, couldn\'t find any results\nthat matched your filter
+
+ All books
+ Any Author
+ Any Category
+
+ Update Book
+
+ Filter
+
+ Sort by Rating
+ Sort by Year
+ Sort Alphabetically
+ sorted by rating
+ sorted by year
+ sorted alphabetically
+
+
+ @string/value_any_author
+
+ Albert Camus
+ Aldous Huxley
+ Anonymous
+ Brian Kernighan
+ Carola Lovering
+ Chuck Palahniuk
+ Dale Carnegie
+ David Kushner
+ Dennis Ritchie
+ Douglas Crockford
+ Eric Freeman
+ F. Scott FitzGerald
+ Frederich Nietzsche
+ Fyodor Dostoevsky
+ George Orwell
+ Ivan Turgenev
+ Joanne Tompkins
+ Joshua Bloch
+ Khalil Gebran
+ May Cobb
+ Napoleon Hill
+ Niccolo Machiavelli
+ Patrick Keefe
+ Paul Graham
+ Paulo Coelho
+ Robert Martin
+ Samuel Beckett
+ Steve McConnell
+ Steven Levy
+
+
+
+ @string/value_any_category
+
+ Business
+ Classics
+ Computer Science
+ Fiction
+ Nonfiction
+ Philosophy
+ Plays
+ Poetry
+ Thriller
+
+
+
+ @string/sort_by_rating
+ @string/sort_by_year
+ @string/sort_alphabetically
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/styles.xml b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1fdc23f
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/build.gradle b/09-sort-and-filter-data/Starter/Bookshelf/build.gradle
new file mode 100644
index 0000000..e2ff5e1
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.5.0"
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.5'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/gradle.properties b/09-sort-and-filter-data/Starter/Bookshelf/gradle.properties
new file mode 100644
index 0000000..98bed16
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar b/09-sort-and-filter-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/09-sort-and-filter-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties b/09-sort-and-filter-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..17dc309
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue May 04 23:12:02 EEST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/gradlew b/09-sort-and-filter-data/Starter/Bookshelf/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/gradlew.bat b/09-sort-and-filter-data/Starter/Bookshelf/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/09-sort-and-filter-data/Starter/Bookshelf/settings.gradle b/09-sort-and-filter-data/Starter/Bookshelf/settings.gradle
new file mode 100644
index 0000000..6dfc5f9
--- /dev/null
+++ b/09-sort-and-filter-data/Starter/Bookshelf/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "Bookshelf"
\ No newline at end of file