Browse code

Initial commit (losing old history)

Dario Rodriguez authored on 08/04/2026 17:25:38
Showing 181 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+*.iml
2
+.gradle
3
+/local.properties
4
+/.idea/caches
5
+/.idea/libraries
6
+/.idea/modules.xml
7
+/.idea/workspace.xml
8
+/.idea/navEditor.xml
9
+/.idea/assetWizardSettings.xml
10
+/.idea/deploymentTargetDropDown.xml
11
+.DS_Store
12
+/build
13
+/captures
14
+.externalNativeBuild
15
+.cxx
16
+local.properties
0 17
new file mode 100644
1 18
Binary files /dev/null and b/AudioNotesKeyStore.jks differ
2 19
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+## 👋 Welcome Dev!, Thanks for making this `Audio Notes App` great ♥️.
2
+
3
+### 💬 What you can do
4
+
5
+You can contribute us by `filing issues`, `bugs` and `PRs`.
6
+
7
+### ✅ Contributing guidelines:
8
+
9
+- Open issue regarding proposed change.
10
+- Repo owner will contact you there.
11
+- If your proposed change is approved, Fork this repo and do changes.
12
+- Open PR against latest `dev` branch. Add nice description in PR.
13
+- You're done!
0 14
new file mode 100644
... ...
@@ -0,0 +1,201 @@
1
+                                 Apache License
2
+                           Version 2.0, January 2004
3
+                        http://www.apache.org/licenses/
4
+
5
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+   1. Definitions.
8
+
9
+      "License" shall mean the terms and conditions for use, reproduction,
10
+      and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+      "Licensor" shall mean the copyright owner or entity authorized by
13
+      the copyright owner that is granting the License.
14
+
15
+      "Legal Entity" shall mean the union of the acting entity and all
16
+      other entities that control, are controlled by, or are under common
17
+      control with that entity. For the purposes of this definition,
18
+      "control" means (i) the power, direct or indirect, to cause the
19
+      direction or management of such entity, whether by contract or
20
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+      outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+      "You" (or "Your") shall mean an individual or Legal Entity
24
+      exercising permissions granted by this License.
25
+
26
+      "Source" form shall mean the preferred form for making modifications,
27
+      including but not limited to software source code, documentation
28
+      source, and configuration files.
29
+
30
+      "Object" form shall mean any form resulting from mechanical
31
+      transformation or translation of a Source form, including but
32
+      not limited to compiled object code, generated documentation,
33
+      and conversions to other media types.
34
+
35
+      "Work" shall mean the work of authorship, whether in Source or
36
+      Object form, made available under the License, as indicated by a
37
+      copyright notice that is included in or attached to the work
38
+      (an example is provided in the Appendix below).
39
+
40
+      "Derivative Works" shall mean any work, whether in Source or Object
41
+      form, that is based on (or derived from) the Work and for which the
42
+      editorial revisions, annotations, elaborations, or other modifications
43
+      represent, as a whole, an original work of authorship. For the purposes
44
+      of this License, Derivative Works shall not include works that remain
45
+      separable from, or merely link (or bind by name) to the interfaces of,
46
+      the Work and Derivative Works thereof.
47
+
48
+      "Contribution" shall mean any work of authorship, including
49
+      the original version of the Work and any modifications or additions
50
+      to that Work or Derivative Works thereof, that is intentionally
51
+      submitted to Licensor for inclusion in the Work by the copyright owner
52
+      or by an individual or Legal Entity authorized to submit on behalf of
53
+      the copyright owner. For the purposes of this definition, "submitted"
54
+      means any form of electronic, verbal, or written communication sent
55
+      to the Licensor or its representatives, including but not limited to
56
+      communication on electronic mailing lists, source code control systems,
57
+      and issue tracking systems that are managed by, or on behalf of, the
58
+      Licensor for the purpose of discussing and improving the Work, but
59
+      excluding communication that is conspicuously marked or otherwise
60
+      designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+      "Contributor" shall mean Licensor and any individual or Legal Entity
63
+      on behalf of whom a Contribution has been received by Licensor and
64
+      subsequently incorporated within the Work.
65
+
66
+   2. Grant of Copyright License. Subject to the terms and conditions of
67
+      this License, each Contributor hereby grants to You a perpetual,
68
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+      copyright license to reproduce, prepare Derivative Works of,
70
+      publicly display, publicly perform, sublicense, and distribute the
71
+      Work and such Derivative Works in Source or Object form.
72
+
73
+   3. Grant of Patent License. Subject to the terms and conditions of
74
+      this License, each Contributor hereby grants to You a perpetual,
75
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+      (except as stated in this section) patent license to make, have made,
77
+      use, offer to sell, sell, import, and otherwise transfer the Work,
78
+      where such license applies only to those patent claims licensable
79
+      by such Contributor that are necessarily infringed by their
80
+      Contribution(s) alone or by combination of their Contribution(s)
81
+      with the Work to which such Contribution(s) was submitted. If You
82
+      institute patent litigation against any entity (including a
83
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+      or a Contribution incorporated within the Work constitutes direct
85
+      or contributory patent infringement, then any patent licenses
86
+      granted to You under this License for that Work shall terminate
87
+      as of the date such litigation is filed.
88
+
89
+   4. Redistribution. You may reproduce and distribute copies of the
90
+      Work or Derivative Works thereof in any medium, with or without
91
+      modifications, and in Source or Object form, provided that You
92
+      meet the following conditions:
93
+
94
+      (a) You must give any other recipients of the Work or
95
+          Derivative Works a copy of this License; and
96
+
97
+      (b) You must cause any modified files to carry prominent notices
98
+          stating that You changed the files; and
99
+
100
+      (c) You must retain, in the Source form of any Derivative Works
101
+          that You distribute, all copyright, patent, trademark, and
102
+          attribution notices from the Source form of the Work,
103
+          excluding those notices that do not pertain to any part of
104
+          the Derivative Works; and
105
+
106
+      (d) If the Work includes a "NOTICE" text file as part of its
107
+          distribution, then any Derivative Works that You distribute must
108
+          include a readable copy of the attribution notices contained
109
+          within such NOTICE file, excluding those notices that do not
110
+          pertain to any part of the Derivative Works, in at least one
111
+          of the following places: within a NOTICE text file distributed
112
+          as part of the Derivative Works; within the Source form or
113
+          documentation, if provided along with the Derivative Works; or,
114
+          within a display generated by the Derivative Works, if and
115
+          wherever such third-party notices normally appear. The contents
116
+          of the NOTICE file are for informational purposes only and
117
+          do not modify the License. You may add Your own attribution
118
+          notices within Derivative Works that You distribute, alongside
119
+          or as an addendum to the NOTICE text from the Work, provided
120
+          that such additional attribution notices cannot be construed
121
+          as modifying the License.
122
+
123
+      You may add Your own copyright statement to Your modifications and
124
+      may provide additional or different license terms and conditions
125
+      for use, reproduction, or distribution of Your modifications, or
126
+      for any such Derivative Works as a whole, provided Your use,
127
+      reproduction, and distribution of the Work otherwise complies with
128
+      the conditions stated in this License.
129
+
130
+   5. Submission of Contributions. Unless You explicitly state otherwise,
131
+      any Contribution intentionally submitted for inclusion in the Work
132
+      by You to the Licensor shall be under the terms and conditions of
133
+      this License, without any additional terms or conditions.
134
+      Notwithstanding the above, nothing herein shall supersede or modify
135
+      the terms of any separate license agreement you may have executed
136
+      with Licensor regarding such Contributions.
137
+
138
+   6. Trademarks. This License does not grant permission to use the trade
139
+      names, trademarks, service marks, or product names of the Licensor,
140
+      except as required for reasonable and customary use in describing the
141
+      origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+   7. Disclaimer of Warranty. Unless required by applicable law or
144
+      agreed to in writing, Licensor provides the Work (and each
145
+      Contributor provides its Contributions) on an "AS IS" BASIS,
146
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+      implied, including, without limitation, any warranties or conditions
148
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+      PARTICULAR PURPOSE. You are solely responsible for determining the
150
+      appropriateness of using or redistributing the Work and assume any
151
+      risks associated with Your exercise of permissions under this License.
152
+
153
+   8. Limitation of Liability. In no event and under no legal theory,
154
+      whether in tort (including negligence), contract, or otherwise,
155
+      unless required by applicable law (such as deliberate and grossly
156
+      negligent acts) or agreed to in writing, shall any Contributor be
157
+      liable to You for damages, including any direct, indirect, special,
158
+      incidental, or consequential damages of any character arising as a
159
+      result of this License or out of the use or inability to use the
160
+      Work (including but not limited to damages for loss of goodwill,
161
+      work stoppage, computer failure or malfunction, or any and all
162
+      other commercial damages or losses), even if such Contributor
163
+      has been advised of the possibility of such damages.
164
+
165
+   9. Accepting Warranty or Additional Liability. While redistributing
166
+      the Work or Derivative Works thereof, You may choose to offer,
167
+      and charge a fee for, acceptance of support, warranty, indemnity,
168
+      or other liability obligations and/or rights consistent with this
169
+      License. However, in accepting such obligations, You may act only
170
+      on Your own behalf and on Your sole responsibility, not on behalf
171
+      of any other Contributor, and only if You agree to indemnify,
172
+      defend, and hold each Contributor harmless for any liability
173
+      incurred by, or claims asserted against, such Contributor by reason
174
+      of your accepting any such warranty or additional liability.
175
+
176
+   END OF TERMS AND CONDITIONS
177
+
178
+   APPENDIX: How to apply the Apache License to your work.
179
+
180
+      To apply the Apache License to your work, attach the following
181
+      boilerplate notice, with the fields enclosed by brackets "[]"
182
+      replaced with your own identifying information. (Don't include
183
+      the brackets!)  The text should be enclosed in the appropriate
184
+      comment syntax for the file format. We also recommend that a
185
+      file or class name and description of purpose be included on the
186
+      same "printed page" as the copyright notice for easier
187
+      identification within third-party archives.
188
+
189
+   Copyright 2021 Samson Achiaga
190
+
191
+   Licensed under the Apache License, Version 2.0 (the "License");
192
+   you may not use this file except in compliance with the License.
193
+   You may obtain a copy of the License at
194
+
195
+       http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+   Unless required by applicable law or agreed to in writing, software
198
+   distributed under the License is distributed on an "AS IS" BASIS,
199
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+   See the License for the specific language governing permissions and
201
+   limitations under the License.
0 202
new file mode 100644
... ...
@@ -0,0 +1,152 @@
1
+# AudioNotes 📙
2
+A simple open source audio note-taking 📝 Android application built to describe the use of Modern Android development tools. 🏗. *Made with love ❤️ by [Sammie_kt](https://github.com/certified84)*
3
+
4
+<br />
5
+
6
+***Find the latest stable release here👇***
7
+
8
+[![AudioNotes](https://github.com/certified84/AudioNote/blob/master/app/src/main/res/drawable/logo.png)](https://github.com/certified84/AudioNote/releases/latest)
9
+
10
+[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
11
+     alt="Get it on F-Droid"
12
+     height="80">](https://f-droid.org/packages/com.certified.audionote/)
13
+
14
+<br />
15
+
16
+***Find the design on figma here👇***
17
+
18
+[![AudioNotes](https://github.com/certified84/AudioNote/blob/master/app/src/main/res/drawable/figma_logo.png)](https://www.figma.com/file/BxFzSMNrfXy8yrQlr8XWAS/Audio-Notes-Project?node-id=3%3A594)
19
+
20
+<br />
21
+
22
+## Day Mode 🌞
23
+Splash | Onboarding | Home(empty) | Home(content) | 
24
+--- | --- | --- | --- | 
25
+![](https://github.com/certified84/AudioNote/blob/master/Screenshots/splash_day.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/onboarding_day.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/home_empty_day.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/home_day.png) |
26
+
27
+New note | Edit note | Settings | About | 
28
+--- | --- | --- | --- | 
29
+![](https://github.com/certified84/AudioNote/blob/master/Screenshots/new_note.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/edit_note.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/settings_day.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/about_day.png)
30
+
31
+<br />
32
+
33
+## We Support Dark Mode Too 🌚
34
+Splash | Onboarding | Home(empty) | Home(content) | 
35
+--- | --- | --- | --- | 
36
+![](https://github.com/certified84/AudioNote/blob/master/Screenshots/splash_dark.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/onboarding_dark.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/home_empty_dark.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/home_dark.png) |
37
+
38
+New note | Edit note | Settings | About | 
39
+--- | --- | --- | --- | 
40
+![](https://github.com/certified84/AudioNote/blob/master/Screenshots/new_note.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/edit_note.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/settings_dark.png) | ![](https://github.com/certified84/AudioNote/blob/master/Screenshots/about_dark.png)
41
+
42
+<br />
43
+
44
+
45
+## Built With 🛠
46
+- [Kotlin](https://kotlinlang.org/) - First class and official programming language for Android development.
47
+- [Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) - For asynchronous and more..
48
+- [Android Architecture Components](https://developer.android.com/topic/libraries/architecture) - Collection of libraries that help you design robust, testable, and maintainable apps.
49
+  - [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel) - Stores UI-related data that isn't destroyed on UI changes. 
50
+  - [Room](https://developer.android.com/topic/libraries/architecture/room) - SQLite object mapping library.
51
+  - [Jetpack Navigation](https://developer.android.com/guide/navigation) - Navigation refers to the interactions that allow users to navigate across, into, and back out from the different pieces of content within your app
52
+- [DataStore](https://developer.android.com/topic/libraries/architecture/datastore) - Jetpack DataStore is a data storage solution that allows you to store key-value pairs or typed objects with protocol buffers. DataStore uses Kotlin coroutines and Flow to store data asynchronously, consistently, and transactionally.
53
+<!--   - [Stateflow](https://developer.android.com/kotlin/flow/stateflow-and-sharedflow) - StateFlow is a state-holder observable flow that emits the current and new state updates to its collectors. 
54
+  - [Flow](https://kotlinlang.org/docs/reference/coroutines/flow.html) - A flow is an asynchronous version of a Sequence, a type of collection whose values are lazily produced.  -->
55
+- [Material Components for Android](https://github.com/material-components/material-components-android) - Modular and customizable Material Design UI components for Android.
56
+- [Coil for Image loading](https://github.com/coil-kt/coil) - Kotlin based library for loading images in Android.
57
+- [Dagger Hilt](https://github.com/google/dagger/tree/master/java/dagger/hilt) - Hilt provides a standard way to incorporate Dagger dependency injection into an Android application. For more information.
58
+- [Easy permissions](https://github.com/vmadalin/easypermissions-ktx) - 🔓 Kotlin version of the popular google/easypermissions wrapper library to simplify basic system permissions logic on Android M or higher.
59
+- [TimerX](https://github.com/arsvechkarev/TimerX) - Android timer and stopwatch library.
60
+
61
+<!-- <br />
62
+
63
+## Package Structure 📦
64
+    
65
+    dev.spikeysanju.expenso # Root Package
66
+    ├── di                  # Hilt DI Modules 
67
+    ├── data                # For data handling.
68
+    │   ├── local           # Local Persistence Database. Room (SQLite) database
69
+    |   │   ├── dao         # Data Access Object for Room   
70
+    |   |   |── database    # Database Instance
71
+    |
72
+    ├── model               # Model classes [Transaction]
73
+    |
74
+    |-- repo                # Used to handle all data operations
75
+    |
76
+    ├── view                # Activity/Fragment View layer
77
+    │   ├── main            # Main root folder
78
+    |   │   ├── main        # Main Activity for RecyclerView
79
+    |   │   └── viewmodel   # Transaction ViewModel
80
+    |   │   ├── adapter     # Adapter for RecyclerView
81
+    │   ├── Dashboard       # Dashboard root folder
82
+    |   |   |__ dashboard   # Dashboard 
83
+    │   ├── Add             # Add Transaction root folder
84
+    |   |   |__ add         # Add Transaction 
85
+    │   ├── Edit            # Edit Transaction root folder
86
+    |   |   |__ edit        # Edit Transaction
87
+    │   ├── Details         # Add Transaction root folder
88
+    |   |   |__ details     # Transaction Details
89
+    │   ├── About           # About root folder
90
+    |   |   |__ about       # About 
91
+    │   ├── Dialog          # All Dialogs root folder
92
+    |   |   |__ dialog      # Error Dialog 
93
+    ├── utils               # All extension functions
94
+
95
+
96
+<br />
97
+ -->
98
+
99
+## Architecture 🗼
100
+This app uses [***MVVM (Model View View-Model)***](https://developer.android.com/jetpack/docs/guide#recommended-app-arch) architecture.
101
+
102
+![](https://github.com/TheCodeMonks/Notes-App/blob/master/screenshots/ANDROID%20ROOM%20DB%20DIAGRAM.jpg)
103
+
104
+## Build-tool 🧰
105
+You need to have [Android Studio](https://developer.android.com/studio) to build this project.
106
+
107
+<br />
108
+
109
+## Credit 🙌
110
+Credit goes to [Shazomii's Notely](https://github.com/shazomii/Notely) for project inspiration
111
+
112
+<br />
113
+
114
+## Contribute 🤝
115
+If you want to contribute to this app, you're always welcome!
116
+See [Contributing Guidelines](https://github.com/certified84/AudioNote/blob/master/CONTRIBUTING.md). 
117
+
118
+<br>
119
+
120
+## Contact 📩
121
+Have a project? DM us at 👇
122
+
123
+Drop a mail to:- achiagasamson5@gmail.com
124
+
125
+<br>
126
+
127
+## Donation 💰
128
+If this project help you reduce time to develop, you can give me a cup of coffee :) 
129
+
130
+<a href="https://www.buymeacoffee.com/SammieKt" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
131
+
132
+## License 🔖
133
+```
134
+    Apache 2.0 License
135
+
136
+
137
+    Copyright 2023 Samson Achiaga
138
+
139
+    Licensed under the Apache License, Version 2.0 (the "License");
140
+    you may not use this file except in compliance with the License.
141
+    You may obtain a copy of the License at
142
+
143
+       http://www.apache.org/licenses/LICENSE-2.0
144
+
145
+    Unless required by applicable law or agreed to in writing, software
146
+    distributed under the License is distributed on an "AS IS" BASIS,
147
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148
+    See the License for the specific language governing permissions and
149
+    limitations under the License.
150
+
151
+```
152
+
0 153
new file mode 100644
1 154
Binary files /dev/null and b/Screenshots/Screenshot_20220211-160800.png differ
2 155
new file mode 100644
3 156
Binary files /dev/null and b/Screenshots/Screenshot_20220211-160805.png differ
4 157
new file mode 100644
5 158
Binary files /dev/null and b/Screenshots/Screenshot_20220211-161703.png differ
6 159
new file mode 100644
7 160
Binary files /dev/null and b/Screenshots/about_dark.png differ
8 161
new file mode 100644
9 162
Binary files /dev/null and b/Screenshots/about_day.png differ
10 163
new file mode 100644
11 164
Binary files /dev/null and b/Screenshots/edit_note.png differ
12 165
new file mode 100644
13 166
Binary files /dev/null and b/Screenshots/home_dark.png differ
14 167
new file mode 100644
15 168
Binary files /dev/null and b/Screenshots/home_day.png differ
16 169
new file mode 100644
17 170
Binary files /dev/null and b/Screenshots/home_empty_dark.png differ
18 171
new file mode 100644
19 172
Binary files /dev/null and b/Screenshots/home_empty_day.png differ
20 173
new file mode 100644
21 174
Binary files /dev/null and b/Screenshots/new_note.png differ
22 175
new file mode 100644
23 176
Binary files /dev/null and b/Screenshots/onboarding_dark.png differ
24 177
new file mode 100644
25 178
Binary files /dev/null and b/Screenshots/onboarding_day.png differ
26 179
new file mode 100644
27 180
Binary files /dev/null and b/Screenshots/settings_dark.png differ
28 181
new file mode 100644
29 182
Binary files /dev/null and b/Screenshots/settings_day.png differ
30 183
new file mode 100644
31 184
Binary files /dev/null and b/Screenshots/splash_dark.png differ
32 185
new file mode 100644
33 186
Binary files /dev/null and b/Screenshots/splash_day.png differ
34 187
new file mode 100644
35 188
Binary files /dev/null and b/app-release-unsigned-aligned.apk differ
36 189
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+/build
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,141 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+plugins {
18
+    id("com.android.application")
19
+    kotlin("android")
20
+    id("kotlin-kapt")
21
+    id("kotlin-parcelize")
22
+    id("dagger.hilt.android.plugin")
23
+    id("androidx.navigation.safeargs.kotlin")
24
+    id("com.google.devtools.ksp")
25
+    id("org.jetbrains.kotlin.plugin.compose") version "2.1.0"
26
+    kotlin("plugin.serialization") version "2.1.0"
27
+}
28
+
29
+android {
30
+    compileSdk = 35
31
+    namespace = "com.certified.audionote"
32
+    
33
+    defaultConfig {
34
+        applicationId = "com.certified.audionote"
35
+        minSdk = 21
36
+        targetSdk = 35
37
+        versionCode = 7
38
+        versionName = "0.1.5.2"
39
+        
40
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
41
+        
42
+        ksp {
43
+            arg("generateKotlin", "true")
44
+        }
45
+    }
46
+    
47
+    buildTypes {
48
+        release {
49
+            isMinifyEnabled = false
50
+            isShrinkResources = false
51
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
52
+        }
53
+    }
54
+    
55
+    compileOptions {
56
+        sourceCompatibility = JavaVersion.VERSION_17
57
+        targetCompatibility = JavaVersion.VERSION_17
58
+    }
59
+    
60
+    kotlinOptions {
61
+        jvmTarget = "17"
62
+    }
63
+    
64
+    buildFeatures {
65
+        dataBinding = true
66
+        viewBinding = true
67
+        compose = true
68
+    }
69
+}
70
+
71
+dependencies {
72
+    
73
+    implementation("androidx.core:core-ktx:1.15.0")
74
+    implementation("androidx.appcompat:appcompat:1.7.0")
75
+    implementation("com.google.android.material:material:1.12.0")
76
+    implementation("androidx.constraintlayout:constraintlayout:2.2.0")
77
+    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
78
+    implementation("androidx.navigation:navigation-fragment-ktx:2.8.5")
79
+    implementation("androidx.navigation:navigation-ui-ktx:2.8.5")
80
+    implementation("androidx.legacy:legacy-support-v4:1.0.0")
81
+    implementation("androidx.preference:preference-ktx:1.2.1")
82
+    implementation("androidx.work:work-runtime-ktx:2.10.0")
83
+    implementation("androidx.core:core-splashscreen:1.0.1")
84
+    
85
+    //  Compose
86
+    implementation(platform("androidx.compose:compose-bom:2024.12.01"))
87
+    implementation("androidx.compose.material3:material3")
88
+    implementation("androidx.compose.material:material-icons-extended:1.7.6")
89
+    implementation("androidx.compose.ui:ui-tooling-preview")
90
+    debugImplementation("androidx.compose.ui:ui-tooling")
91
+    implementation("androidx.activity:activity-compose:1.9.3")
92
+    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7")
93
+    implementation("androidx.navigation:navigation-compose:2.8.5")
94
+    
95
+    //  Intuit ssp/sdp
96
+    implementation("com.intuit.ssp:ssp-android:1.1.0")
97
+    implementation("com.intuit.sdp:sdp-android:1.1.0")
98
+    
99
+    //  Coroutines
100
+    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
101
+    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
102
+    
103
+    //  Room persistence library
104
+    implementation("androidx.room:room-runtime:2.6.1")
105
+    implementation("androidx.room:room-ktx:2.6.1")
106
+    ksp("androidx.room:room-compiler:2.6.1")
107
+    
108
+    //  Datastore
109
+    implementation("androidx.datastore:datastore-preferences:1.1.1")
110
+    
111
+    //  Hilt
112
+    implementation("com.google.dagger:hilt-android:2.53.1")
113
+    ksp("com.google.dagger:hilt-compiler:2.53.1")
114
+    ksp("androidx.hilt:hilt-compiler:1.2.0")
115
+    implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
116
+    
117
+    //  TimerX
118
+    implementation("com.github.arsvechkarev:TimerX:3.1.0")
119
+    
120
+    //  Serilization
121
+    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
122
+    
123
+    //  Page indicator
124
+    implementation("com.github.romandanylyk:PageIndicatorView:v.1.0.3")
125
+    
126
+    //  Window
127
+    implementation("androidx.window:window:1.3.0")
128
+    
129
+    //  Integration testing
130
+    androidTestImplementation("androidx.test.ext:junit:1.2.1")
131
+    androidTestImplementation("com.google.truth:truth:1.1.3")
132
+    androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
133
+    androidTestImplementation(platform("androidx.compose:compose-bom:2024.12.01"))
134
+    androidTestImplementation("androidx.compose.ui:ui-test-junit4")
135
+    debugImplementation("androidx.compose.ui:ui-test-manifest")
136
+    
137
+    //  Unit testing
138
+    testImplementation("junit:junit:4.13.2")
139
+    testImplementation("com.google.truth:truth:1.1.3")
140
+    testImplementation("androidx.room:room-testing:2.6.1")
141
+}
0 142
\ No newline at end of file
1 143
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+# Add project specific ProGuard rules here.
2
+# You can control the set of applied configuration files using the
3
+# proguardFiles setting in build.gradle.kts.
4
+#
5
+# For more details, see
6
+#   http://developer.android.com/guide/developing/tools/proguard.html
7
+
8
+# If your project uses WebView with JS, uncomment the following
9
+# and specify the fully qualified class name to the JavaScript interface
10
+# class:
11
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12
+#   public *;
13
+#}
14
+
15
+# Uncomment this to preserve the line number information for
16
+# debugging stack traces.
17
+#-keepattributes SourceFile,LineNumberTable
18
+
19
+# If you keep the line number information, uncomment this to
20
+# hide the original source file name.
21
+#-renamesourcefileattribute SourceFile
0 22
\ No newline at end of file
1 23
new file mode 100644
2 24
Binary files /dev/null and b/app/release/app-release.apk differ
3 25
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+{
2
+  "version": 3,
3
+  "artifactType": {
4
+    "type": "APK",
5
+    "kind": "Directory"
6
+  },
7
+  "applicationId": "com.certified.audionote",
8
+  "variantName": "release",
9
+  "elements": [
10
+    {
11
+      "type": "SINGLE",
12
+      "filters": [],
13
+      "attributes": [],
14
+      "versionCode": 7,
15
+      "versionName": "0.1.5.2",
16
+      "outputFile": "app-release.apk"
17
+    }
18
+  ],
19
+  "elementType": "File"
20
+}
0 21
\ No newline at end of file
1 22
new file mode 100644
... ...
@@ -0,0 +1,40 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote
18
+
19
+import androidx.test.platform.app.InstrumentationRegistry
20
+import androidx.test.ext.junit.runners.AndroidJUnit4
21
+
22
+import org.junit.Test
23
+import org.junit.runner.RunWith
24
+
25
+import org.junit.Assert.*
26
+
27
+/**
28
+ * Instrumented test, which will execute on an Android device.
29
+ *
30
+ * See [testing documentation](http://d.android.com/tools/testing).
31
+ */
32
+@RunWith(AndroidJUnit4::class)
33
+class ExampleInstrumentedTest {
34
+    @Test
35
+    fun useAppContext() {
36
+        // Context of the app under test.
37
+        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
38
+        assertEquals("com.certified.audionote", appContext.packageName)
39
+    }
40
+}
0 41
\ No newline at end of file
1 42
new file mode 100644
... ...
@@ -0,0 +1,55 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
18
+
19
+    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
20
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
21
+    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
22
+    <uses-permission android:name="android.permission.VIBRATE" />
23
+
24
+    <application
25
+        android:name=".AudioNotesApp"
26
+        android:allowBackup="true"
27
+        android:icon="@mipmap/ic_logo"
28
+        android:label="@string/app_name"
29
+        android:roundIcon="@mipmap/ic_logo_round"
30
+        android:supportsRtl="true"
31
+        android:theme="@style/Theme.AudioNote">
32
+        <activity
33
+            android:name=".ui.main.MainActivity"
34
+            android:exported="true">
35
+            <intent-filter>
36
+                <action android:name="android.intent.action.MAIN" />
37
+
38
+                <category android:name="android.intent.category.LAUNCHER" />
39
+            </intent-filter>
40
+        </activity>
41
+        <receiver android:name=".ui.AlertReceiver" />
42
+
43
+        <provider
44
+            android:name="androidx.core.content.FileProvider"
45
+            android:authorities="com.certified.audionote.provider"
46
+            android:exported="false"
47
+            android:grantUriPermissions="true">
48
+            <meta-data
49
+                android:name="android.support.FILE_PROVIDER_PATHS"
50
+                android:resource="@xml/file_paths">
51
+            </meta-data>
52
+        </provider>
53
+    </application>
54
+
55
+</manifest>
0 56
\ No newline at end of file
1 57
new file mode 100644
2 58
Binary files /dev/null and b/app/src/main/ic_logo-playstore.png differ
3 59
new file mode 100644
... ...
@@ -0,0 +1,23 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote
18
+
19
+import android.app.Application
20
+import dagger.hilt.android.HiltAndroidApp
21
+
22
+@HiltAndroidApp
23
+class AudioNotesApp : Application()
0 24
\ No newline at end of file
1 25
new file mode 100644
... ...
@@ -0,0 +1,79 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.adapter
18
+
19
+import android.graphics.Paint
20
+import android.view.View
21
+import android.widget.ImageView
22
+import android.widget.TextView
23
+import androidx.databinding.BindingAdapter
24
+import androidx.recyclerview.widget.RecyclerView
25
+import com.certified.audionote.model.Note
26
+
27
+@BindingAdapter("listItems")
28
+fun bindItemRecyclerView(recyclerView: RecyclerView, data: List<Note>?) {
29
+    val adapter = recyclerView.adapter as NoteRecyclerAdapter
30
+    adapter.submitList(data)
31
+}
32
+
33
+@BindingAdapter("visible")
34
+fun View.setVisible(visible: Boolean) {
35
+    visibility = if (visible) View.VISIBLE else View.GONE
36
+}
37
+
38
+@BindingAdapter("editNoteVisible")
39
+fun View.setEditNoteVisible(audioLength: Long) {
40
+    visibility = when (audioLength) {
41
+        0L -> View.GONE
42
+        else -> View.VISIBLE
43
+    }
44
+}
45
+
46
+@BindingAdapter("timerVisible")
47
+fun View.setTimerVisible(audioLength: Long) {
48
+    visibility = when (audioLength) {
49
+        0L -> View.GONE
50
+        else -> View.VISIBLE
51
+    }
52
+}
53
+
54
+@BindingAdapter("strikeThrough")
55
+fun strikeThrough(textView: TextView, strikeThrough: Boolean) {
56
+    if (strikeThrough) {
57
+        textView.paintFlags = Paint.STRIKE_THRU_TEXT_FLAG
58
+    } else {
59
+        textView.paintFlags = 0
60
+    }
61
+}
62
+
63
+@BindingAdapter("timeText")
64
+fun TextView.timeText(value: Long) {
65
+    text = if (value >= 3600)
66
+        String.format("%02d:%02d:%02d", value / 3600, (value % 3600) / 60, value % 60)
67
+    else
68
+        String.format("%02d:%02d", (value % 3600) / 60, value % 60)
69
+}
70
+
71
+@BindingAdapter("image")
72
+fun ImageView.loadImage(image: Int) {
73
+    setImageResource(image)
74
+}
75
+
76
+@BindingAdapter("sizeText")
77
+fun TextView.sizeText(value: String) {
78
+    text = "${value}MB"
79
+}
0 80
\ No newline at end of file
1 81
new file mode 100644
... ...
@@ -0,0 +1,63 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.adapter
18
+
19
+import android.view.LayoutInflater
20
+import android.view.ViewGroup
21
+import androidx.recyclerview.widget.DiffUtil
22
+import androidx.recyclerview.widget.ListAdapter
23
+import androidx.recyclerview.widget.RecyclerView
24
+import com.certified.audionote.databinding.ItemNoteBinding
25
+import com.certified.audionote.model.Note
26
+
27
+class NoteRecyclerAdapter(private val onItemClick: (note: Note) -> Unit) :
28
+    ListAdapter<Note, NoteRecyclerAdapter.ViewHolder>(DIFF_CALLBACK) {
29
+
30
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
31
+        val binding =
32
+            ItemNoteBinding.inflate(LayoutInflater.from(parent.context), parent, false)
33
+        return ViewHolder(binding)
34
+    }
35
+
36
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
37
+        val currentItem = getItem(position)
38
+        holder.bind(currentItem)
39
+    }
40
+
41
+    inner class ViewHolder(private val binding: ItemNoteBinding) :
42
+        RecyclerView.ViewHolder(binding.root) {
43
+
44
+        fun bind(note: Note) {
45
+            binding.note = note
46
+        }
47
+
48
+        init {
49
+            itemView.setOnClickListener {
50
+                val position = adapterPosition
51
+                if (position != RecyclerView.NO_POSITION)
52
+                    onItemClick.invoke(getItem(position))
53
+            }
54
+        }
55
+    }
56
+
57
+    companion object {
58
+        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Note>() {
59
+            override fun areItemsTheSame(oldItem: Note, newItem: Note) = oldItem.id == newItem.id
60
+            override fun areContentsTheSame(oldItem: Note, newItem: Note) = oldItem == newItem
61
+        }
62
+    }
63
+}
0 64
\ No newline at end of file
1 65
new file mode 100644
... ...
@@ -0,0 +1,55 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.adapter
18
+
19
+import android.view.LayoutInflater
20
+import android.view.ViewGroup
21
+import androidx.recyclerview.widget.DiffUtil
22
+import androidx.recyclerview.widget.ListAdapter
23
+import androidx.recyclerview.widget.RecyclerView
24
+import com.certified.audionote.databinding.ItemSliderBinding
25
+import com.certified.audionote.model.SliderItem
26
+
27
+class ViewPagerAdapter() :
28
+    ListAdapter<SliderItem, ViewPagerAdapter.ViewHolder>(DIFF_CALLBACK) {
29
+
30
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
31
+        val binding = ItemSliderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
32
+        return ViewHolder(binding)
33
+    }
34
+
35
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
36
+        val currentItem = getItem(position)
37
+        holder.bind(currentItem)
38
+    }
39
+
40
+    inner class ViewHolder(val binding: ItemSliderBinding) : RecyclerView.ViewHolder(binding.root) {
41
+        fun bind(sliderItem: SliderItem) {
42
+            binding.sliderItem = sliderItem
43
+        }
44
+    }
45
+
46
+    companion object {
47
+        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<SliderItem>() {
48
+            override fun areItemsTheSame(oldItem: SliderItem, newItem: SliderItem) =
49
+                oldItem.title == newItem.title
50
+
51
+            override fun areContentsTheSame(oldItem: SliderItem, newItem: SliderItem) =
52
+                oldItem == newItem
53
+        }
54
+    }
55
+}
0 56
\ No newline at end of file
1 57
new file mode 100644
... ...
@@ -0,0 +1,40 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.database
18
+
19
+import androidx.room.*
20
+import com.certified.audionote.model.Note
21
+import kotlinx.coroutines.flow.Flow
22
+
23
+@Dao
24
+interface AudioNotesDAO {
25
+
26
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
27
+    suspend fun insertNote(note: Note)
28
+
29
+    @Update
30
+    suspend fun updateNote(note: Note)
31
+
32
+    @Delete
33
+    suspend fun deleteNote(note: Note)
34
+
35
+    @Query("SELECT * FROM notes_table WHERE id = :noteId")
36
+    fun getNote(noteId: Int): Flow<Note>
37
+
38
+    @Query("SELECT * FROM notes_table ORDER BY id DESC")
39
+    fun getAllNotes(): Flow<List<Note>?>
40
+}
0 41
\ No newline at end of file
1 42
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.database
18
+
19
+import androidx.room.Database
20
+import androidx.room.RoomDatabase
21
+import androidx.room.TypeConverters
22
+import com.certified.audionote.model.Note
23
+import com.certified.audionote.utils.Converters
24
+
25
+@Database(entities = [Note::class], version = 1, exportSchema = false)
26
+@TypeConverters(Converters::class)
27
+abstract class AudioNotesDatabase : RoomDatabase() {
28
+
29
+    abstract fun audioNotesDao(): AudioNotesDAO
30
+}
0 31
\ No newline at end of file
1 32
new file mode 100644
... ...
@@ -0,0 +1,35 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.di
18
+
19
+import android.app.Application
20
+import android.content.Context
21
+import dagger.Module
22
+import dagger.Provides
23
+import dagger.hilt.InstallIn
24
+import dagger.hilt.android.components.ActivityRetainedComponent
25
+import dagger.hilt.android.qualifiers.ApplicationContext
26
+
27
+@InstallIn(ActivityRetainedComponent::class)
28
+@Module
29
+object ApplicationModule {
30
+
31
+    @Provides
32
+    fun provideAppContext(@ApplicationContext context: Application): Context {
33
+        return context.applicationContext
34
+    }
35
+}
0 36
\ No newline at end of file
1 37
new file mode 100644
... ...
@@ -0,0 +1,46 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.di
18
+
19
+import android.content.Context
20
+import androidx.room.Room
21
+import com.certified.audionote.database.AudioNotesDAO
22
+import com.certified.audionote.database.AudioNotesDatabase
23
+import dagger.Module
24
+import dagger.Provides
25
+import dagger.hilt.InstallIn
26
+import dagger.hilt.android.qualifiers.ApplicationContext
27
+import dagger.hilt.components.SingletonComponent
28
+import javax.inject.Singleton
29
+
30
+@InstallIn(SingletonComponent::class)
31
+@Module
32
+class DatabaseModule {
33
+
34
+    @Singleton
35
+    @Provides
36
+    fun provideAudioNotesDatabase(@ApplicationContext context: Context) =
37
+        Room.databaseBuilder(context, AudioNotesDatabase::class.java, "audio_notes_database.db")
38
+            .fallbackToDestructiveMigration()
39
+            .build()
40
+
41
+    @Singleton
42
+    @Provides
43
+    fun provideNoteDao(database: AudioNotesDatabase): AudioNotesDAO {
44
+        return database.audioNotesDao()
45
+    }
46
+}
0 47
\ No newline at end of file
1 48
new file mode 100644
... ...
@@ -0,0 +1,67 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.features.settings
18
+
19
+import android.os.Bundle
20
+import android.view.LayoutInflater
21
+import android.view.View
22
+import android.view.ViewGroup
23
+import androidx.fragment.app.Fragment
24
+import androidx.navigation.NavController
25
+import androidx.navigation.Navigation
26
+import com.certified.audionote.R
27
+import com.certified.audionote.databinding.FragmentSettingsBinding
28
+import com.certified.audionote.utils.Extensions.flags
29
+import com.certified.audionote.utils.Extensions.safeNavigate
30
+
31
+class SettingsFragment : Fragment() {
32
+
33
+    private var _binding: FragmentSettingsBinding? = null
34
+    private val binding get() = _binding!!
35
+    private lateinit var navController: NavController
36
+
37
+    override fun onCreateView(
38
+        inflater: LayoutInflater,
39
+        container: ViewGroup?,
40
+        savedInstanceState: Bundle?
41
+    ): View {
42
+        // Inflate the layout for this fragment
43
+        _binding = FragmentSettingsBinding.inflate(inflater, container, false)
44
+        return binding.root
45
+    }
46
+
47
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
48
+        super.onViewCreated(view, savedInstanceState)
49
+
50
+        navController = Navigation.findNavController(view)
51
+
52
+        binding.apply {
53
+            btnBack.setOnClickListener { navController.safeNavigate(SettingsFragmentDirections.actionSettingsFragmentToHomeFragment()) }
54
+            groupAbout.setOnClickListener { navController.safeNavigate(SettingsFragmentDirections.actionSettingsFragmentToAboutFragment()) }
55
+        }
56
+    }
57
+
58
+    override fun onResume() {
59
+        super.onResume()
60
+        flags(R.color.fragment_background)
61
+    }
62
+
63
+    override fun onDestroyView() {
64
+        super.onDestroyView()
65
+        _binding = null
66
+    }
67
+}
0 68
\ No newline at end of file
1 69
new file mode 100644
... ...
@@ -0,0 +1,191 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.features.settings
18
+
19
+import android.content.res.*
20
+import androidx.compose.foundation.*
21
+import androidx.compose.foundation.layout.*
22
+import androidx.compose.foundation.shape.*
23
+import androidx.compose.material.icons.*
24
+import androidx.compose.material.icons.automirrored.outlined.*
25
+import androidx.compose.material.icons.outlined.*
26
+import androidx.compose.material3.*
27
+import androidx.compose.runtime.*
28
+import androidx.compose.ui.*
29
+import androidx.compose.ui.draw.*
30
+import androidx.compose.ui.graphics.vector.*
31
+import androidx.compose.ui.res.*
32
+import androidx.compose.ui.text.*
33
+import androidx.compose.ui.tooling.preview.*
34
+import androidx.compose.ui.unit.*
35
+import com.certified.audionote.R
36
+import com.certified.audionote.ui.theme.*
37
+
38
+/**
39
+ * Created by MJ Jacobs on 2024/12/28 at 14:54
40
+ */
41
+
42
+@Composable
43
+fun SettingsScreen(
44
+    modifier: Modifier = Modifier
45
+) {
46
+    SettingsScreenContent(
47
+        modifier = modifier
48
+    )
49
+}
50
+
51
+@Composable
52
+private fun SettingsScreenContent(
53
+    modifier: Modifier = Modifier
54
+) {
55
+    Column(
56
+        modifier = modifier.fillMaxSize(),
57
+        content = {
58
+            //  Display title
59
+            Text(
60
+                modifier = Modifier
61
+                    .fillMaxWidth()
62
+                    .padding(start = largePadding + 24.dp),
63
+                text = stringResource(R.string.display),
64
+                style = TextStyle(
65
+                    color = if (isSystemInDarkTheme()) primaryDark else primaryLight,
66
+                    fontSize = 20.sp
67
+                )
68
+            )
69
+            Spacer(modifier = Modifier.height(normalPadding))
70
+            
71
+            //  Theme selection
72
+            SettingsRowItem(
73
+                icon = Icons.Outlined.BrightnessMedium,
74
+                imageDescription = stringResource(R.string.theme),
75
+                title = stringResource(R.string.theme),
76
+                description = stringResource(R.string.theme_system_default),
77
+                onClick = { /*TODO*/ }
78
+            )
79
+            Spacer(modifier = Modifier.height(normalPadding))
80
+            //  About title
81
+            Text(
82
+                modifier = Modifier
83
+                    .fillMaxWidth()
84
+                    .padding(start = largePadding + 24.dp),
85
+                text = stringResource(R.string.about),
86
+                style = TextStyle(
87
+                    color = if (isSystemInDarkTheme()) primaryDark else primaryLight,
88
+                    fontSize = 20.sp
89
+                )
90
+            )
91
+            Spacer(modifier = Modifier.height(normalPadding))
92
+            
93
+            //  Theme selection
94
+            SettingsRowItem(
95
+                icon = Icons.Outlined.Person,
96
+                imageDescription = stringResource(R.string.developer),
97
+                title = stringResource(R.string.developer),
98
+                description = stringResource(R.string.developer_nick),
99
+                onClick = { /*TODO*/ }
100
+            )
101
+            Spacer(modifier = Modifier.height(normalPadding))
102
+            
103
+            //  Theme selection
104
+            SettingsRowItem(
105
+                icon = Icons.Outlined.Code,
106
+                imageDescription = stringResource(R.string.contribute),
107
+                title = stringResource(R.string.contribute),
108
+                description = stringResource(R.string.contribute_summary),
109
+                onClick = { /*TODO*/ }
110
+            )
111
+            Spacer(modifier = Modifier.height(normalPadding))
112
+            
113
+            //  Theme selection
114
+            SettingsRowItem(
115
+                icon = Icons.AutoMirrored.Outlined.ContactSupport,
116
+                imageDescription = stringResource(R.string.contact_feedback),
117
+                title = stringResource(R.string.contact_feedback),
118
+                description = stringResource(R.string.developer_mail),
119
+                onClick = { /*TODO*/ }
120
+            )
121
+            Spacer(modifier = Modifier.height(normalPadding))
122
+            
123
+            //  Theme selection
124
+            SettingsRowItem(
125
+                icon = Icons.Outlined.Info,
126
+                imageDescription = stringResource(R.string.about),
127
+                title = stringResource(R.string.about),
128
+                description = stringResource(R.string.app_version_licence_and_more),
129
+                onClick = { /*TODO*/ }
130
+            )
131
+            Spacer(modifier = Modifier.height(normalPadding))
132
+        }
133
+    )
134
+}
135
+
136
+@Composable
137
+private fun SettingsRowItem(
138
+    icon: ImageVector,
139
+    imageDescription: String,
140
+    title: String,
141
+    description: String,
142
+    onClick: () -> Unit,
143
+) {
144
+    Row(
145
+        modifier = Modifier
146
+            .fillMaxWidth()
147
+            .clip(RoundedCornerShape(defaultCornerSize))
148
+            .clickable { onClick() },
149
+        verticalAlignment = Alignment.CenterVertically,
150
+        content = {
151
+            //  Icon
152
+            Icon(
153
+                modifier = Modifier.padding(normalPadding),
154
+                imageVector = icon,
155
+                contentDescription = imageDescription
156
+            )
157
+            
158
+            Column(
159
+                modifier = Modifier.fillMaxWidth(),
160
+                content = {
161
+                    //  Title text field
162
+                    Text(
163
+                        text = title,
164
+                        style = MaterialTheme.typography.titleMedium
165
+                    )
166
+                    
167
+                    Text(
168
+                        text = description,
169
+                        style = MaterialTheme.typography.bodyMedium
170
+                    )
171
+                }
172
+            )
173
+        }
174
+    )
175
+}
176
+
177
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, showBackground = true)
178
+@Composable
179
+private fun PreviewSettingsScreenContentLightTheme() {
180
+    AudioNoteTheme {
181
+        SettingsScreenContent()
182
+    }
183
+}
184
+
185
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, showBackground = true)
186
+@Composable
187
+private fun PreviewSettingsScreenContentDarkTheme() {
188
+    AudioNoteTheme {
189
+        SettingsScreenContent()
190
+    }
191
+}
0 192
\ No newline at end of file
1 193
new file mode 100644
... ...
@@ -0,0 +1,56 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.model
18
+
19
+import android.os.Parcelable
20
+import androidx.room.Entity
21
+import androidx.room.PrimaryKey
22
+import com.certified.audionote.utils.colors
23
+import com.certified.audionote.utils.currentDate
24
+import kotlinx.parcelize.Parcelize
25
+
26
+/**
27
+ * The Note class represent the domain model i.e the
28
+ * object visible to the app user.
29
+ *
30
+ * @param id        id of the note
31
+ * @param title     title of the note
32
+ * @param description      content of the note
33
+ * @param color     color of the note
34
+ * @param lastModificationDate      date the note was created/modified
35
+ * @param audioLength       The length of the audio recording
36
+ * @param size      Basically the size of the audio in MB in the device
37
+ * @param started   whether or note the reminder is active
38
+ * @param reminder  date set for a reminder in the note
39
+ *
40
+ **/
41
+
42
+@Parcelize
43
+@Entity(tableName = "notes_table")
44
+data class Note(
45
+    var title: String = "",
46
+    var description: String = "",
47
+    var color: Int = colors.random(),
48
+    var lastModificationDate: Long = currentDate().timeInMillis,
49
+    var size: String = "",
50
+    var audioLength: Long = -1L,
51
+    var filePath: String = "",
52
+    var started: Boolean = false,
53
+    var reminder: Long? = null,
54
+    @PrimaryKey(autoGenerate = true)
55
+    var id: Int = 0,
56
+) : Parcelable
0 57
\ No newline at end of file
1 58
new file mode 100644
... ...
@@ -0,0 +1,29 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.model
18
+
19
+/**
20
+ * The SliderItem class represent a domain model i.e an
21
+ * object visible to the app user. It is used in conjunction
22
+ * with ViewPager2 to create the Onboarding
23
+ *
24
+ * @param image             image of the sliderItem
25
+ * @param title             title of the sliderItem
26
+ * @param description      description of the sliderItem
27
+ *
28
+ **/
29
+data class SliderItem (val image: Int, val title: String, val description: String)
0 30
\ No newline at end of file
1 31
new file mode 100644
... ...
@@ -0,0 +1,78 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.navigation
18
+
19
+import android.app.Activity
20
+import androidx.compose.foundation.layout.*
21
+import androidx.compose.material3.*
22
+import androidx.compose.runtime.*
23
+import androidx.compose.ui.*
24
+import androidx.navigation.compose.*
25
+import com.certified.audionote.navigation.nav_hosts.*
26
+import com.certified.audionote.ui.theme.*
27
+import com.certified.audionote.utils.*
28
+
29
+/**
30
+ * Created by MJ Jacobs on 2024/12/28 at 13:56
31
+ */
32
+
33
+//  TODO: 2024/12/28 - Decide on whether to use height or width to measure screen orientation
34
+
35
+@Composable
36
+fun AudioNoteNavHost(
37
+    activity: Activity,
38
+) {
39
+    val navController = rememberNavController()
40
+    
41
+    Scaffold(
42
+        content = { paddingValues ->
43
+            Box(
44
+                modifier = Modifier.padding(
45
+                    top = paddingValues.calculateTopPadding().plus(normalPadding),
46
+                    start = normalPadding,
47
+                    end = normalPadding,
48
+                    bottom = paddingValues.calculateBottomPadding().plus(normalPadding)
49
+                )
50
+            ) {
51
+                calculateWindowSize(
52
+                    activity = activity,
53
+                    windowWidthSizeClassChange = { windowSize ->
54
+                        when (windowSize) {
55
+                            WindowSizeClass.COMPACT -> {
56
+                                CompactNavHost(
57
+                                    navController = navController
58
+                                )
59
+                            }
60
+                            
61
+                            WindowSizeClass.MEDIUM -> {
62
+                                MediumNavHost(
63
+                                    navController = navController
64
+                                )
65
+                            }
66
+                            
67
+                            WindowSizeClass.EXPANDED -> {
68
+                                ExpandedNavHost(
69
+                                    navController = navController
70
+                                )
71
+                            }
72
+                        }
73
+                    }
74
+                )
75
+            }
76
+        }
77
+    )
78
+}
0 79
\ No newline at end of file
1 80
new file mode 100644
... ...
@@ -0,0 +1,41 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.navigation
18
+
19
+import kotlinx.serialization.Serializable
20
+
21
+/**
22
+ * Created by MJ Jacobs on 2024/12/28 at 13:40
23
+ */
24
+
25
+@Serializable
26
+data object Home
27
+
28
+@Serializable
29
+data object OnBoarding
30
+
31
+@Serializable
32
+data class EditNote(val noteId: String)
33
+
34
+@Serializable
35
+data object AddNote
36
+
37
+@Serializable
38
+data object Settings
39
+
40
+@Serializable
41
+data object About
0 42
\ No newline at end of file
1 43
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.navigation
18
+
19
+import androidx.navigation.*
20
+
21
+/**
22
+ * Created by MJ Jacobs on 2024/12/28 at 13:50
23
+ */
24
+
25
+fun NavHostController.goToEditNote(noteId: String) {
26
+    navigate(EditNote(noteId = noteId))
27
+}
28
+
29
+fun NavHostController.goToAddNote() {
30
+    navigate(AddNote)
31
+}
32
+
33
+fun NavHostController.goToSettings(){
34
+    navigate(Settings)
35
+}
36
+
37
+fun NavHostController.goToHome(){
38
+    navigate(Home)
39
+}
40
+
41
+fun NavHostController.goToAbout(){
42
+    navigate(About)
43
+}
0 44
\ No newline at end of file
1 45
new file mode 100644
... ...
@@ -0,0 +1,32 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.navigation.nav_graph
18
+
19
+import androidx.navigation.*
20
+import androidx.navigation.compose.*
21
+import com.certified.audionote.features.settings.*
22
+import com.certified.audionote.navigation.*
23
+
24
+/**
25
+ * Created by MJ Jacobs on 2024/12/28 at 15:57
26
+ */
27
+
28
+fun NavGraphBuilder.settings(navController: NavHostController){
29
+    composable<Settings> {
30
+        SettingsScreen()
31
+    }
32
+}
0 33
\ No newline at end of file
1 34
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.navigation.nav_hosts
18
+
19
+import androidx.compose.foundation.layout.*
20
+import androidx.compose.runtime.*
21
+import androidx.compose.ui.*
22
+import androidx.navigation.*
23
+import androidx.navigation.compose.*
24
+import com.certified.audionote.navigation.*
25
+import com.certified.audionote.navigation.nav_graph.*
26
+
27
+/**
28
+ * Created by MJ Jacobs on 2024/12/28 at 13:56
29
+ */
30
+
31
+@Composable
32
+fun CompactNavHost(
33
+    navController: NavHostController
34
+) {
35
+    
36
+    NavHost(
37
+        modifier = Modifier.fillMaxSize(),
38
+        startDestination = Settings,
39
+        navController = navController
40
+    ) {
41
+        settings(navController = navController)
42
+    }
43
+}
0 44
\ No newline at end of file
1 45
new file mode 100644
... ...
@@ -0,0 +1,31 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.navigation.nav_hosts
18
+
19
+import androidx.compose.runtime.*
20
+import androidx.navigation.*
21
+
22
+/**
23
+ * Created by MJ Jacobs on 2024/12/28 at 13:56
24
+ */
25
+
26
+@Composable
27
+fun ExpandedNavHost(
28
+    navController: NavHostController
29
+) {
30
+
31
+}
0 32
\ No newline at end of file
1 33
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.navigation.nav_hosts
18
+
19
+import androidx.compose.runtime.*
20
+import androidx.navigation.*
21
+
22
+/**
23
+ * Created by MJ Jacobs on 2024/12/28 at 13:56
24
+ */
25
+
26
+@Composable
27
+fun MediumNavHost(
28
+    navController: NavHostController
29
+) {
30
+}
0 31
\ No newline at end of file
1 32
new file mode 100644
... ...
@@ -0,0 +1,36 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.repository
18
+
19
+import com.certified.audionote.database.AudioNotesDAO
20
+import com.certified.audionote.model.Note
21
+import kotlinx.coroutines.flow.Flow
22
+import javax.inject.Inject
23
+import javax.inject.Singleton
24
+
25
+@Singleton
26
+class Repository @Inject constructor(private val audioNotesDAO: AudioNotesDAO) {
27
+
28
+    val allNotes: Flow<List<Note>?> = audioNotesDAO.getAllNotes()
29
+    suspend fun insertNote(note: Note) = audioNotesDAO.insertNote(note)
30
+
31
+    suspend fun updateNote(note: Note) = audioNotesDAO.updateNote(note)
32
+
33
+    suspend fun deleteNote(note: Note) = audioNotesDAO.deleteNote(note)
34
+
35
+    fun getNote(noteId: Int): Flow<Note> = audioNotesDAO.getNote(noteId)
36
+}
0 37
\ No newline at end of file
1 38
new file mode 100644
... ...
@@ -0,0 +1,56 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import android.os.Bundle
20
+import android.view.LayoutInflater
21
+import android.view.View
22
+import android.view.ViewGroup
23
+import androidx.fragment.app.Fragment
24
+import androidx.navigation.NavController
25
+import androidx.navigation.Navigation
26
+import com.certified.audionote.databinding.FragmentAboutBinding
27
+import com.certified.audionote.utils.Extensions.safeNavigate
28
+
29
+class AboutFragment : Fragment() {
30
+
31
+    private var _binding: FragmentAboutBinding? = null
32
+    private val binding get() = _binding!!
33
+    private lateinit var navController: NavController
34
+
35
+    override fun onCreateView(
36
+        inflater: LayoutInflater, container: ViewGroup?,
37
+        savedInstanceState: Bundle?
38
+    ): View {
39
+        // Inflate the layout for this fragment
40
+        _binding = FragmentAboutBinding.inflate(layoutInflater, container, false)
41
+        return binding.root
42
+    }
43
+
44
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
45
+        super.onViewCreated(view, savedInstanceState)
46
+
47
+        navController = Navigation.findNavController(view)
48
+
49
+        binding.btnBack.setOnClickListener { navController.safeNavigate(AboutFragmentDirections.actionAboutFragmentToSettingsFragment()) }
50
+    }
51
+
52
+    override fun onDestroyView() {
53
+        super.onDestroyView()
54
+        _binding = null
55
+    }
56
+}
0 57
\ No newline at end of file
1 58
new file mode 100644
... ...
@@ -0,0 +1,342 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import android.Manifest
20
+import android.app.DatePickerDialog
21
+import android.app.TimePickerDialog
22
+import android.content.pm.PackageManager
23
+import android.media.MediaRecorder
24
+import android.os.Bundle
25
+import android.view.LayoutInflater
26
+import android.view.View
27
+import android.view.ViewGroup
28
+import android.view.WindowManager
29
+import android.widget.DatePicker
30
+import android.widget.TimePicker
31
+import androidx.activity.result.contract.ActivityResultContracts
32
+import androidx.core.content.ContextCompat
33
+import androidx.core.content.res.ResourcesCompat
34
+import androidx.fragment.app.Fragment
35
+import androidx.fragment.app.viewModels
36
+import androidx.navigation.NavController
37
+import androidx.navigation.Navigation
38
+import androidx.navigation.fragment.navArgs
39
+import com.certified.audionote.R
40
+import com.certified.audionote.databinding.DialogEditReminderBinding
41
+import com.certified.audionote.databinding.FragmentAddNoteBinding
42
+import com.certified.audionote.model.Note
43
+import com.certified.audionote.utils.Extensions.safeNavigate
44
+import com.certified.audionote.utils.Extensions.showKeyboardFor
45
+import com.certified.audionote.utils.Extensions.showToast
46
+import com.certified.audionote.utils.ReminderAvailableState
47
+import com.certified.audionote.utils.cancelAlarm
48
+import com.certified.audionote.utils.currentDate
49
+import com.certified.audionote.utils.filePath
50
+import com.certified.audionote.utils.formatReminderDate
51
+import com.certified.audionote.utils.roundOffDecimal
52
+import com.certified.audionote.utils.startAlarm
53
+import com.google.android.material.bottomsheet.BottomSheetDialog
54
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
55
+import dagger.hilt.android.AndroidEntryPoint
56
+import timerx.*
57
+import java.io.File
58
+import java.io.IOException
59
+import java.util.Calendar
60
+import java.util.concurrent.TimeUnit
61
+
62
+@AndroidEntryPoint
63
+class AddNoteFragment : Fragment(), DatePickerDialog.OnDateSetListener,
64
+    TimePickerDialog.OnTimeSetListener {
65
+
66
+    private var _binding: FragmentAddNoteBinding? = null
67
+    private val binding get() = _binding!!
68
+
69
+    private val viewModel: NotesViewModel by viewModels()
70
+    private lateinit var navController: NavController
71
+
72
+    private val args: EditNoteFragmentArgs by navArgs()
73
+    private lateinit var _note: Note
74
+    private var isRecording = false
75
+    private var pickedDateTime: Calendar? = null
76
+    private val currentDateTime by lazy { currentDate() }
77
+    private var mediaRecorder: MediaRecorder? = null
78
+    private var file: File? = null
79
+    private var stopWatch: Stopwatch? = null
80
+    private var timer: Timer? = null
81
+
82
+    private val requestAudioRecordingPermissionLauncher =
83
+        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
84
+            if (!isGranted) MaterialAlertDialogBuilder(requireContext()).apply {
85
+                setTitle(getString(R.string.audio_record_permission))
86
+                setMessage(getString(R.string.permission_required))
87
+                setPositiveButton(getString(R.string.ok)) { dialog, _ -> dialog.dismiss() }
88
+                show()
89
+            }
90
+            else startRecording()
91
+        }
92
+
93
+    override fun onCreateView(
94
+        inflater: LayoutInflater, container: ViewGroup?,
95
+        savedInstanceState: Bundle?
96
+    ): View {
97
+        // Inflate the layout for this fragment
98
+        _binding = FragmentAddNoteBinding.inflate(layoutInflater, container, false)
99
+        return binding.root
100
+    }
101
+
102
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
103
+        super.onViewCreated(view, savedInstanceState)
104
+
105
+        navController = Navigation.findNavController(view)
106
+
107
+        binding.lifecycleOwner = viewLifecycleOwner
108
+        binding.viewModel = viewModel
109
+        args.note.let {
110
+            _note = it
111
+            binding.note = it
112
+        }
113
+
114
+        binding.btnBack.setOnClickListener {
115
+            if (binding.etNoteTitle.text.toString().isNotBlank())
116
+                saveNote()
117
+            else
118
+                try {
119
+                    file?.delete()
120
+                } catch (e: Exception) {
121
+                    e.printStackTrace()
122
+                }
123
+            navController.safeNavigate(AddNoteFragmentDirections.actionAddNoteFragmentToHomeFragment())
124
+        }
125
+        binding.cardAddReminder.setOnClickListener {
126
+            if (viewModel.reminderAvailableState.value == ReminderAvailableState.NO_REMINDER)
127
+                pickDate()
128
+            else
129
+                openEditReminderDialog()
130
+        }
131
+        binding.btnRecord.setOnClickListener { recordAudio() }
132
+        binding.fabSaveNote.setOnClickListener {
133
+            if (binding.etNoteTitle.text.toString().isNotBlank())
134
+                saveNote()
135
+            else {
136
+                showToast(requireContext().getString(R.string.title_required))
137
+                binding.etNoteTitle.requestFocus()
138
+            }
139
+        }
140
+    }
141
+
142
+    override fun onResume() {
143
+        super.onResume()
144
+        binding.etNoteTitle.apply {
145
+            requestFocus()
146
+            showKeyboardFor(requireContext())
147
+        }
148
+        updateStatusBarColor(binding.note!!.color)
149
+    }
150
+
151
+    override fun onDestroyView() {
152
+        super.onDestroyView()
153
+        mediaRecorder = null
154
+        timer?.apply {
155
+            stop()
156
+            reset()
157
+        }
158
+        timer = null
159
+        stopWatch?.apply {
160
+            stop()
161
+            reset()
162
+        }
163
+        stopWatch = null
164
+        _binding = null
165
+    }
166
+
167
+    private fun recordAudio() {
168
+        binding.apply {
169
+            if (!isRecording) {
170
+                if (ContextCompat.checkSelfPermission(
171
+                        requireContext(), Manifest.permission.RECORD_AUDIO
172
+                    ) == PackageManager.PERMISSION_GRANTED
173
+                ) {
174
+                    btnRecord.setImageDrawable(
175
+                        ResourcesCompat.getDrawable(
176
+                            resources,
177
+                            R.drawable.ic_mic_recording,
178
+                            null
179
+                        )
180
+                    ).run {
181
+                        try {
182
+                            file?.delete()
183
+                        } catch (e: Exception) {
184
+                            e.printStackTrace()
185
+                        }
186
+                        isRecording = true
187
+                        startRecording()
188
+                    }
189
+                } else if (shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO))
190
+                    MaterialAlertDialogBuilder(requireContext()).apply {
191
+                        setTitle(getString(R.string.audio_record_permission))
192
+                        setMessage(getString(R.string.permission_required))
193
+                        setPositiveButton(getString(R.string.ok)) { dialog, _ -> dialog.dismiss() }
194
+                        show()
195
+                    }
196
+                else requestAudioRecordingPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
197
+            } else {
198
+                btnRecord.setImageDrawable(
199
+                    ResourcesCompat.getDrawable(
200
+                        resources, R.drawable.ic_mic_not_recording, null
201
+                    )
202
+                )
203
+                    .run {
204
+                        isRecording = false
205
+                        stopRecording()
206
+                    }
207
+            }
208
+        }
209
+    }
210
+
211
+    override fun onDateSet(p0: DatePicker?, p1: Int, p2: Int, p3: Int) {
212
+        pickedDateTime = currentDate()
213
+        pickedDateTime!!.set(p1, p2, p3)
214
+        val hourOfDay = currentDateTime.get(Calendar.HOUR_OF_DAY)
215
+        val minuteOfDay = currentDateTime.get(Calendar.MINUTE)
216
+        val timePickerDialog =
217
+            TimePickerDialog(requireContext(), this, hourOfDay, minuteOfDay, false)
218
+        timePickerDialog.setOnDismissListener {
219
+            viewModel._reminderAvailableState.value = ReminderAvailableState.HAS_REMINDER
220
+            _note.reminder = pickedDateTime!!.timeInMillis
221
+            binding.tvReminderDate.text = formatReminderDate(pickedDateTime!!.timeInMillis)
222
+        }
223
+        timePickerDialog.show()
224
+    }
225
+
226
+    override fun onTimeSet(p0: TimePicker?, p1: Int, p2: Int) {
227
+        pickedDateTime!!.set(Calendar.HOUR_OF_DAY, p1)
228
+        pickedDateTime!!.set(Calendar.MINUTE, p2)
229
+        if (pickedDateTime!!.timeInMillis <= currentDate().timeInMillis) {
230
+            pickedDateTime!!.run {
231
+                set(Calendar.DAY_OF_MONTH, currentDateTime.get(Calendar.DAY_OF_MONTH) + 1)
232
+                set(Calendar.YEAR, currentDateTime.get(Calendar.YEAR))
233
+                set(Calendar.MONTH, currentDateTime.get(Calendar.MONTH))
234
+            }
235
+        }
236
+    }
237
+
238
+    private fun pickDate() {
239
+        val startYear = currentDateTime.get(Calendar.YEAR)
240
+        val startMonth = currentDateTime.get(Calendar.MONTH)
241
+        val startDay = currentDateTime.get(Calendar.DAY_OF_MONTH)
242
+        val datePickerDialog =
243
+            DatePickerDialog(requireContext(), this, startYear, startMonth, startDay)
244
+        datePickerDialog.show()
245
+    }
246
+
247
+    private fun openEditReminderDialog() {
248
+        val view = DialogEditReminderBinding.inflate(layoutInflater)
249
+        val bottomSheetDialog = BottomSheetDialog(requireContext())
250
+        view.apply {
251
+            note = _note
252
+            btnDeleteReminder.setOnClickListener {
253
+                viewModel._reminderAvailableState.value = ReminderAvailableState.NO_REMINDER
254
+                _note.reminder = null
255
+                bottomSheetDialog.dismiss()
256
+            }
257
+            btnModifyReminder.setOnClickListener {
258
+                bottomSheetDialog.dismiss()
259
+                pickDate()
260
+            }
261
+        }
262
+        bottomSheetDialog.edgeToEdgeEnabled
263
+        bottomSheetDialog.setContentView(view.root)
264
+        bottomSheetDialog.show()
265
+    }
266
+
267
+    private fun saveNote() {
268
+        binding.apply {
269
+            stopRecording()
270
+            if (_note.audioLength <= 0) {
271
+                showToast(requireContext().getString(R.string.record_note_before_saving))
272
+                return
273
+            }
274
+            val note = _note.copy(
275
+                title = etNoteTitle.text.toString().trim(),
276
+                description = etNoteDescription.text.toString().trim()
277
+            )
278
+            this@AddNoteFragment.viewModel.insertNote(note)
279
+            showToast(requireContext().getString(R.string.note_saved))
280
+            if (pickedDateTime?.timeInMillis != null && pickedDateTime!!.timeInMillis <= currentDateTime.timeInMillis)
281
+                startAlarm(requireContext(), pickedDateTime!!.timeInMillis, note)
282
+            navController.safeNavigate(AddNoteFragmentDirections.actionAddNoteFragmentToHomeFragment())
283
+        }
284
+    }
285
+
286
+    private fun startRecording() {
287
+        val filePath = filePath(requireActivity())
288
+        val fileName = "${System.currentTimeMillis()}.3gp"
289
+        _note.filePath = "$filePath/$fileName"
290
+
291
+        stopWatch = buildStopwatch {
292
+            startFormat("MM:SS")
293
+            onTick { millis: Long, time: CharSequence->
294
+                binding.tvTimer.text = time
295
+            }
296
+            changeFormatWhen(1, TimeUnit.HOURS, "HH:MM:SS")
297
+        }
298
+        
299
+
300
+        mediaRecorder = MediaRecorder().apply {
301
+            setAudioSource(MediaRecorder.AudioSource.MIC)
302
+            setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
303
+            setOutputFile("$filePath/$fileName")
304
+            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
305
+            try {
306
+                prepare()
307
+                start()
308
+                stopWatch!!.start()
309
+                file = File("$filePath/$fileName")
310
+            } catch (e: IOException) {
311
+                showToast(requireContext().getString(R.string.error_occurred))
312
+            }
313
+        }
314
+    }
315
+
316
+    private fun stopRecording() {
317
+        mediaRecorder?.apply {
318
+            stop()
319
+            release()
320
+        }
321
+        mediaRecorder = null
322
+        stopWatch?.apply {
323
+            stop()
324
+            _note.audioLength = stopWatch!!.currentTimeInMillis / 1000
325
+            reset()
326
+        }
327
+        stopWatch = null
328
+        if (_note.audioLength <= 0)
329
+            return
330
+        file = File(_note.filePath)
331
+        val fileByte = (file!!.readBytes().size.toDouble() / 1048576.00)
332
+        val fileSize = roundOffDecimal(fileByte)
333
+        _note.size = fileSize
334
+    }
335
+
336
+    private fun updateStatusBarColor(color: Int) {
337
+        val window = requireActivity().window
338
+        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
339
+//        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
340
+        window.statusBarColor = color
341
+    }
342
+}
0 343
\ No newline at end of file
1 344
new file mode 100644
... ...
@@ -0,0 +1,65 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import android.content.BroadcastReceiver
20
+import android.content.Context
21
+import android.content.Intent
22
+import androidx.work.Data
23
+import androidx.work.ExistingWorkPolicy
24
+import androidx.work.OneTimeWorkRequestBuilder
25
+import androidx.work.WorkManager
26
+import com.certified.audionote.utils.NotificationWorker
27
+import java.util.concurrent.TimeUnit
28
+
29
+class AlertReceiver : BroadcastReceiver() {
30
+    override fun onReceive(context: Context, intent: Intent) {
31
+
32
+        val noteId = intent.getIntExtra("noteId", 0)
33
+        val noteTitle = intent.getStringExtra("noteTitle")
34
+        val noteDescription = intent.getStringExtra("noteDescription")
35
+        val noteColor = intent.getIntExtra("noteColor", -1)
36
+        val noteLastModificationDate = intent.getLongExtra("noteLastModificationDate", -1L)
37
+        val noteSize = intent.getStringExtra("noteSize")
38
+        val noteAudioLength = intent.getLongExtra("noteAudioLength", 0L)
39
+        val noteFilePath = intent.getStringExtra("noteFilePath")
40
+        val noteStarted = intent.getBooleanExtra("noteStarted", false)
41
+        val noteReminder = intent.getLongExtra("noteReminder", -1L)
42
+
43
+        val data = Data.Builder()
44
+        data.apply {
45
+            putInt("noteId", noteId)
46
+            putString("noteTitle", noteTitle)
47
+            putString("noteDescription", noteDescription)
48
+            putInt("noteColor", noteColor)
49
+            putLong("noteLastModificationDate", noteLastModificationDate)
50
+            putString("noteSize", noteSize)
51
+            putLong("noteAudioLength", noteAudioLength)
52
+            putString("noteFilePath", noteFilePath)
53
+            putBoolean("noteStarted", noteStarted)
54
+            putLong("noteReminder", noteReminder)
55
+        }
56
+        val notificationRequest = OneTimeWorkRequestBuilder<NotificationWorker>()
57
+        notificationRequest
58
+            .setInitialDelay(10000, TimeUnit.MILLISECONDS).setInputData(data.build())
59
+        WorkManager.getInstance(context).beginUniqueWork(
60
+            "Audio Notes notification work",
61
+            ExistingWorkPolicy.REPLACE,
62
+            notificationRequest.build()
63
+        ).enqueue()
64
+    }
65
+}
0 66
\ No newline at end of file
1 67
new file mode 100644
... ...
@@ -0,0 +1,383 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import android.app.DatePickerDialog
20
+import android.app.TimePickerDialog
21
+import android.content.Context
22
+import android.content.Intent
23
+import android.media.MediaPlayer
24
+import android.os.Bundle
25
+import android.util.Log
26
+import android.view.LayoutInflater
27
+import android.view.View
28
+import android.view.ViewGroup
29
+import android.view.WindowManager
30
+import android.widget.DatePicker
31
+import android.widget.TimePicker
32
+import androidx.core.content.FileProvider
33
+import androidx.core.content.res.ResourcesCompat
34
+import androidx.fragment.app.Fragment
35
+import androidx.fragment.app.viewModels
36
+import androidx.lifecycle.lifecycleScope
37
+import androidx.navigation.NavController
38
+import androidx.navigation.Navigation
39
+import androidx.navigation.fragment.navArgs
40
+import com.certified.audionote.R
41
+import com.certified.audionote.databinding.DialogEditReminderBinding
42
+import com.certified.audionote.databinding.FragmentEditNoteBinding
43
+import com.certified.audionote.model.Note
44
+import com.certified.audionote.utils.Extensions.safeNavigate
45
+import com.certified.audionote.utils.Extensions.showToast
46
+import com.certified.audionote.utils.ReminderAvailableState
47
+import com.certified.audionote.utils.ReminderCompletionState
48
+import com.certified.audionote.utils.cancelAlarm
49
+import com.certified.audionote.utils.currentDate
50
+import com.certified.audionote.utils.formatReminderDate
51
+import com.certified.audionote.utils.startAlarm
52
+import com.google.android.material.bottomsheet.BottomSheetDialog
53
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
54
+import dagger.hilt.android.AndroidEntryPoint
55
+import kotlinx.coroutines.Dispatchers
56
+import kotlinx.coroutines.launch
57
+import timerx.*
58
+import java.io.File
59
+import java.io.IOException
60
+import java.util.Calendar
61
+import java.util.concurrent.TimeUnit
62
+
63
+@AndroidEntryPoint
64
+class EditNoteFragment : Fragment(), DatePickerDialog.OnDateSetListener,
65
+    TimePickerDialog.OnTimeSetListener {
66
+    
67
+    private var _binding: FragmentEditNoteBinding? = null
68
+    private val binding get() = _binding!!
69
+    
70
+    private val viewModel: NotesViewModel by viewModels()
71
+    private lateinit var navController: NavController
72
+    
73
+    private val args: EditNoteFragmentArgs by navArgs()
74
+    private lateinit var _note: Note
75
+    private var isPlayingRecord = false
76
+    private var pickedDateTime: Calendar? = null
77
+    private val currentDateTime by lazy { currentDate() }
78
+    private var mediaPlayer: MediaPlayer? = null
79
+    private var file: File? = null
80
+    private var stopWatch: Stopwatch? = null
81
+    private var timer: Timer? = null
82
+    
83
+    override fun onCreateView(
84
+        inflater: LayoutInflater,
85
+        container: ViewGroup?,
86
+        savedInstanceState: Bundle?
87
+    ): View {
88
+        // Inflate the layout for this fragment
89
+        _binding = FragmentEditNoteBinding.inflate(layoutInflater, container, false)
90
+        return binding.root
91
+    }
92
+    
93
+    override fun onViewCreated(
94
+        view: View,
95
+        savedInstanceState: Bundle?
96
+    ) {
97
+        super.onViewCreated(view, savedInstanceState)
98
+        
99
+        navController = Navigation.findNavController(view)
100
+        
101
+        binding.lifecycleOwner = viewLifecycleOwner
102
+        binding.viewModel = viewModel
103
+        args.note.let {
104
+            _note = it
105
+            binding.note = it
106
+        }
107
+        
108
+        binding.btnBack.setOnClickListener {
109
+            navController.safeNavigate(EditNoteFragmentDirections.actionEditNoteFragmentToHomeFragment())
110
+        }
111
+        binding.cardAddReminder.setOnClickListener {
112
+            if (viewModel.reminderAvailableState.value == ReminderAvailableState.NO_REMINDER)
113
+                pickDate()
114
+            else
115
+                openEditReminderDialog()
116
+        }
117
+        binding.btnShare.setOnClickListener { shareNote() }
118
+        binding.btnDelete.setOnClickListener { launchDeleteNoteDialog(requireContext()) }
119
+        binding.btnRecord.setOnClickListener { playPauseRecord() }
120
+        binding.fabUpdateNote.setOnClickListener { updateNote() }
121
+        
122
+        setup()
123
+    }
124
+    
125
+    private fun setup() {
126
+        lifecycleScope.launch {
127
+            file = File(_note.filePath)
128
+            Log.d("TAG", "onViewCreated: ${file!!.name}")
129
+        }
130
+        viewModel.apply {
131
+            if (_note.reminder != null) {
132
+                _reminderAvailableState.value = ReminderAvailableState.HAS_REMINDER
133
+                if (currentDate().timeInMillis > args.note.reminder!!) {
134
+                    _reminderCompletionState.value = ReminderCompletionState.COMPLETED
135
+                } else {
136
+                    _reminderCompletionState.value = ReminderCompletionState.ONGOING
137
+                }
138
+            }
139
+        }
140
+    }
141
+    
142
+    override fun onResume() {
143
+        super.onResume()
144
+        updateStatusBarColor(args.note.color)
145
+    }
146
+    
147
+    override fun onDestroyView() {
148
+        super.onDestroyView()
149
+        if (isPlayingRecord)
150
+            mediaPlayer?.apply {
151
+                stop()
152
+                release()
153
+            }
154
+        mediaPlayer = null
155
+        timer?.apply {
156
+            stop()
157
+            reset()
158
+        }
159
+        timer = null
160
+        stopWatch?.apply {
161
+            stop()
162
+            reset()
163
+        }
164
+        stopWatch = null
165
+        _binding = null
166
+    }
167
+    
168
+    private fun playPauseRecord() {
169
+        binding.apply {
170
+            if (!isPlayingRecord)
171
+                btnRecord.setImageDrawable(
172
+                    ResourcesCompat.getDrawable(
173
+                        resources,
174
+                        R.drawable.ic_audio_playing, null
175
+                    )
176
+                )
177
+                    .run {
178
+                        if (timer == null)
179
+                            startPlayingRecording()
180
+                        else
181
+                            continuePlayingRecording()
182
+                        isPlayingRecord = true
183
+                    }
184
+            else
185
+                btnRecord.setImageDrawable(
186
+                    ResourcesCompat.getDrawable(
187
+                        resources,
188
+                        R.drawable.ic_audio_not_playing, null
189
+                    )
190
+                )
191
+                    .run {
192
+                        if ((timer?.remainingTimeInMillis?.div(1000)) != 0L)
193
+                            pausePlayingRecording()
194
+                        else
195
+                            stopPlayingRecording()
196
+                        isPlayingRecord = false
197
+                    }
198
+        }
199
+    }
200
+    
201
+    private fun updateNote() {
202
+        val note = _note.copy(
203
+            title = binding.etNoteTitle.text.toString().trim(),
204
+            description = binding.etNoteDescription.text.toString().trim(),
205
+            lastModificationDate = currentDate().timeInMillis
206
+        )
207
+        if (note.title.isNotBlank()) {
208
+            viewModel.updateNote(note)
209
+            if (pickedDateTime?.timeInMillis != null && pickedDateTime?.timeInMillis != currentDateTime.timeInMillis)
210
+                startAlarm(requireContext(), pickedDateTime!!.timeInMillis, note)
211
+            navController.safeNavigate(EditNoteFragmentDirections.actionEditNoteFragmentToHomeFragment())
212
+        } else {
213
+            showToast(requireContext().getString(R.string.title_required))
214
+            binding.etNoteTitle.requestFocus()
215
+        }
216
+    }
217
+    
218
+    override fun onDateSet(
219
+        p0: DatePicker?,
220
+        p1: Int,
221
+        p2: Int,
222
+        p3: Int
223
+    ) {
224
+        pickedDateTime = currentDate()
225
+        pickedDateTime!!.set(p1, p2, p3)
226
+        val hourOfDay = currentDateTime.get(Calendar.HOUR_OF_DAY)
227
+        val minuteOfDay = currentDateTime.get(Calendar.MINUTE)
228
+        val timePickerDialog =
229
+            TimePickerDialog(requireContext(), this, hourOfDay, minuteOfDay, false)
230
+        timePickerDialog.setOnDismissListener {
231
+            viewModel._reminderAvailableState.value = ReminderAvailableState.HAS_REMINDER
232
+            viewModel._reminderCompletionState.value = ReminderCompletionState.ONGOING
233
+            _note.reminder = pickedDateTime!!.timeInMillis
234
+            binding.tvReminderDate.text = formatReminderDate(pickedDateTime!!.timeInMillis)
235
+        }
236
+        timePickerDialog.show()
237
+    }
238
+    
239
+    override fun onTimeSet(
240
+        p0: TimePicker?,
241
+        p1: Int,
242
+        p2: Int
243
+    ) {
244
+        pickedDateTime!!.set(Calendar.HOUR_OF_DAY, p1)
245
+        pickedDateTime!!.set(Calendar.MINUTE, p2)
246
+        if (pickedDateTime!!.timeInMillis <= currentDate().timeInMillis) {
247
+            pickedDateTime!!.run {
248
+                set(Calendar.DAY_OF_MONTH, currentDateTime.get(Calendar.DAY_OF_MONTH) + 1)
249
+                set(Calendar.YEAR, currentDateTime.get(Calendar.YEAR))
250
+                set(Calendar.MONTH, currentDateTime.get(Calendar.MONTH))
251
+            }
252
+        }
253
+    }
254
+    
255
+    private fun pickDate() {
256
+        val startYear = currentDateTime.get(Calendar.YEAR)
257
+        val startMonth = currentDateTime.get(Calendar.MONTH)
258
+        val startDay = currentDateTime.get(Calendar.DAY_OF_MONTH)
259
+        val datePickerDialog =
260
+            DatePickerDialog(requireContext(), this, startYear, startMonth, startDay)
261
+        datePickerDialog.show()
262
+    }
263
+    
264
+    private fun openEditReminderDialog() {
265
+        val view = DialogEditReminderBinding.inflate(layoutInflater)
266
+        val bottomSheetDialog = BottomSheetDialog(requireContext())
267
+        view.apply {
268
+            note = _note
269
+            btnDeleteReminder.setOnClickListener {
270
+                viewModel._reminderAvailableState.value = ReminderAvailableState.NO_REMINDER
271
+                _note.reminder = null
272
+                cancelAlarm(requireContext(), _note.id)
273
+                bottomSheetDialog.dismiss()
274
+            }
275
+            btnModifyReminder.setOnClickListener {
276
+                bottomSheetDialog.dismiss()
277
+                pickDate()
278
+            }
279
+        }
280
+        bottomSheetDialog.edgeToEdgeEnabled
281
+        bottomSheetDialog.setContentView(view.root)
282
+        bottomSheetDialog.show()
283
+    }
284
+    
285
+    private fun launchDeleteNoteDialog(context: Context) {
286
+        val materialDialog = MaterialAlertDialogBuilder(context)
287
+        materialDialog.apply {
288
+            setTitle(context.getString(R.string.delete_note))
289
+            setMessage("${context.getString(R.string.confirm_deletion)} ${_note.title}?")
290
+            setNegativeButton(context.getString(R.string.no)) { dialog, _ -> dialog?.dismiss() }
291
+            setPositiveButton(context.getString(R.string.yes)) { _, _ ->
292
+                viewModel.deleteNote(_note)
293
+                lifecycleScope.launch(Dispatchers.IO) { file?.delete() }
294
+                navController.safeNavigate(EditNoteFragmentDirections.actionEditNoteFragmentToHomeFragment())
295
+            }
296
+            show()
297
+        }
298
+    }
299
+    
300
+    private fun startPlayingRecording() {
301
+        timer = buildTimer {
302
+            startTime(_note.audioLength, TimeUnit.SECONDS)
303
+            startFormat(if (_note.audioLength >= 3600000L) "HH:MM:SS" else "MM:SS")
304
+            onTick { millis, time -> binding.tvTimer.text = time }
305
+            actionWhen(0, TimeUnit.SECONDS) {
306
+                binding.btnRecord.setImageDrawable(
307
+                    ResourcesCompat.getDrawable(
308
+                        resources,
309
+                        R.drawable.ic_audio_not_playing,
310
+                        null
311
+                    )
312
+                ).run {
313
+                    isPlayingRecord = false
314
+                    stopPlayingRecording()
315
+                }
316
+            }
317
+        }
318
+        mediaPlayer = MediaPlayer()
319
+        try {
320
+            mediaPlayer?.apply {
321
+                setDataSource(file?.absolutePath)
322
+                prepare()
323
+                start()
324
+            }
325
+            timer!!.start()
326
+        } catch (e: IOException) {
327
+            e.printStackTrace()
328
+            Log.d("TAG", "startPlayingRecording: ${e.localizedMessage}")
329
+            showToast(requireContext().getString(R.string.error_occurred))
330
+        }
331
+    }
332
+    
333
+    private fun pausePlayingRecording() {
334
+        mediaPlayer?.pause()
335
+        timer?.stop()
336
+    }
337
+    
338
+    private fun continuePlayingRecording() {
339
+        mediaPlayer?.start()
340
+        timer?.start()
341
+    }
342
+    
343
+    private fun stopPlayingRecording() {
344
+        mediaPlayer?.apply {
345
+            stop()
346
+            release()
347
+        }
348
+        timer?.apply {
349
+            reset()
350
+            stop()
351
+        }
352
+        timer = null
353
+    }
354
+    
355
+    private fun shareNote() {
356
+        if (file == null) {
357
+            showToast(requireContext().getString(R.string.file_not_found))
358
+            return
359
+        }
360
+        try {
361
+            val uri = FileProvider.getUriForFile(
362
+                requireContext(),
363
+                "com.certified.audionote.provider",
364
+                file!!
365
+            )
366
+            Intent(Intent.ACTION_SEND).apply {
367
+                type = "*/*"
368
+                putExtra(Intent.EXTRA_STREAM, uri)
369
+                startActivity(Intent.createChooser(this, "Share using"))
370
+            }
371
+        } catch (t: Throwable) {
372
+            showToast(requireContext().getString(R.string.error_occurred))
373
+            Log.d("TAG", "shareNote: ${t.localizedMessage}")
374
+        }
375
+    }
376
+    
377
+    private fun updateStatusBarColor(color: Int) {
378
+        val window = requireActivity().window
379
+        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
380
+//        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
381
+        window.statusBarColor = color
382
+    }
383
+}
0 384
\ No newline at end of file
1 385
new file mode 100644
... ...
@@ -0,0 +1,114 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import android.os.Bundle
20
+import android.view.LayoutInflater
21
+import android.view.View
22
+import android.view.ViewGroup
23
+import androidx.fragment.app.Fragment
24
+import androidx.fragment.app.viewModels
25
+import androidx.navigation.NavController
26
+import androidx.navigation.Navigation
27
+import androidx.recyclerview.widget.GridLayoutManager
28
+import com.certified.audionote.R
29
+import com.certified.audionote.adapter.NoteRecyclerAdapter
30
+import com.certified.audionote.databinding.FragmentHomeBinding
31
+import com.certified.audionote.model.Note
32
+import com.certified.audionote.repository.Repository
33
+import com.certified.audionote.utils.Extensions.flags
34
+import com.certified.audionote.utils.Extensions.safeNavigate
35
+import com.google.android.material.bottomsheet.BottomSheetBehavior
36
+import dagger.hilt.android.AndroidEntryPoint
37
+import javax.inject.Inject
38
+
39
+@AndroidEntryPoint
40
+class HomeFragment : Fragment() {
41
+
42
+    private var _binding: FragmentHomeBinding? = null
43
+    private val binding get() = _binding!!
44
+
45
+    @Inject
46
+    lateinit var repository: Repository
47
+    private val viewModel: NotesViewModel by viewModels()
48
+    private lateinit var navController: NavController
49
+
50
+    override fun onCreateView(
51
+        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
52
+    ): View {
53
+        // Inflate the layout for this fragment
54
+        _binding = FragmentHomeBinding.inflate(inflater, container, false)
55
+        return binding.root
56
+    }
57
+
58
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
59
+        super.onViewCreated(view, savedInstanceState)
60
+        navController = Navigation.findNavController(view)
61
+
62
+        binding.viewModel = viewModel
63
+        binding.lifecycleOwner = viewLifecycleOwner
64
+
65
+        NoteRecyclerAdapter { note ->
66
+            val action = HomeFragmentDirections.actionHomeFragmentToEditNoteFragment(note)
67
+            navController.safeNavigate(action)
68
+        }.apply {
69
+            val layoutManager = GridLayoutManager(requireContext(), 2)
70
+            binding.recyclerViewNotes.also {
71
+                it.layoutManager = layoutManager
72
+                it.adapter = this
73
+            }
74
+        }
75
+
76
+        binding.apply {
77
+            btnSettings.setOnClickListener { navController.safeNavigate(HomeFragmentDirections.actionHomeFragmentToSettingsFragment()) }
78
+            fabAddNote.setOnClickListener {
79
+                val action =
80
+                    HomeFragmentDirections.actionHomeFragmentToAddNoteFragment(Note(audioLength = 0L))
81
+                navController.safeNavigate(action)
82
+            }
83
+
84
+            val bottomSheetBehavior =
85
+                BottomSheetBehavior.from(bottomSheetDialogLayout.bottomSheetDialog)
86
+            bottomSheetBehavior.addBottomSheetCallback(object :
87
+                BottomSheetBehavior.BottomSheetCallback() {
88
+                override fun onStateChanged(bottomSheet: View, newState: Int) {
89
+                    if (newState == BottomSheetBehavior.STATE_HIDDEN) bottomSheetBehavior.state =
90
+                        BottomSheetBehavior.STATE_COLLAPSED
91
+                }
92
+
93
+                override fun onSlide(bottomSheet: View, slideOffset: Float) {
94
+//                    Unused
95
+                }
96
+            })
97
+            bottomSheetDialogLayout.linearLayoutCompat.setOnClickListener {
98
+                if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) bottomSheetBehavior.state =
99
+                    BottomSheetBehavior.STATE_EXPANDED
100
+                else bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
101
+            }
102
+        }
103
+    }
104
+
105
+    override fun onResume() {
106
+        super.onResume()
107
+        flags(R.color.fragment_background)
108
+    }
109
+
110
+    override fun onDestroyView() {
111
+        super.onDestroyView()
112
+        _binding = null
113
+    }
114
+}
0 115
\ No newline at end of file
1 116
new file mode 100644
... ...
@@ -0,0 +1,92 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import androidx.lifecycle.ViewModel
20
+import androidx.lifecycle.viewModelScope
21
+import com.certified.audionote.model.Note
22
+import com.certified.audionote.repository.Repository
23
+import com.certified.audionote.utils.ReminderAvailableState
24
+import com.certified.audionote.utils.ReminderCompletionState
25
+import com.certified.audionote.utils.UIState
26
+import dagger.hilt.android.lifecycle.HiltViewModel
27
+import kotlinx.coroutines.Dispatchers
28
+import kotlinx.coroutines.flow.MutableStateFlow
29
+import kotlinx.coroutines.flow.asStateFlow
30
+import kotlinx.coroutines.launch
31
+import javax.inject.Inject
32
+
33
+@HiltViewModel
34
+class NotesViewModel @Inject constructor(private val repository: Repository) : ViewModel() {
35
+
36
+    val _reminderAvailableState = MutableStateFlow(ReminderAvailableState.NO_REMINDER)
37
+    val reminderAvailableState = _reminderAvailableState.asStateFlow()
38
+
39
+    val _reminderCompletionState = MutableStateFlow(ReminderCompletionState.ONGOING)
40
+    val reminderCompletionState = _reminderCompletionState.asStateFlow()
41
+
42
+    private val _uiState = MutableStateFlow(UIState.LOADING)
43
+    val uiState = _uiState.asStateFlow()
44
+
45
+    private val _notes = MutableStateFlow<List<Note>?>(null)
46
+    val notes = _notes.asStateFlow()
47
+
48
+    private val _note = MutableStateFlow<Note?>(null)
49
+    val note = _note.asStateFlow()
50
+
51
+    init {
52
+        getNotes()
53
+    }
54
+
55
+    private fun getNotes() {
56
+        viewModelScope.launch {
57
+            repository.allNotes.collect {
58
+                _notes.value = it
59
+                if (it.isNullOrEmpty())
60
+                    _uiState.value = UIState.EMPTY
61
+                else
62
+                    _uiState.value = UIState.HAS_DATA
63
+            }
64
+        }
65
+    }
66
+
67
+    fun insertNote(note: Note) {
68
+        viewModelScope.launch(Dispatchers.IO) {
69
+            repository.insertNote(note)
70
+        }
71
+    }
72
+
73
+    fun updateNote(note: Note) {
74
+        viewModelScope.launch(Dispatchers.IO) {
75
+            repository.updateNote(note)
76
+        }
77
+    }
78
+
79
+    fun deleteNote(note: Note) {
80
+        viewModelScope.launch(Dispatchers.IO) {
81
+            repository.deleteNote(note)
82
+        }
83
+    }
84
+
85
+    fun getNote(noteId: Int) {
86
+        viewModelScope.launch(Dispatchers.IO) {
87
+            repository.getNote(noteId).collect {
88
+                _note.value = it
89
+            }
90
+        }
91
+    }
92
+}
0 93
\ No newline at end of file
1 94
new file mode 100644
... ...
@@ -0,0 +1,112 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import android.os.Bundle
20
+import android.view.LayoutInflater
21
+import android.view.View
22
+import android.view.ViewGroup
23
+import androidx.datastore.preferences.core.edit
24
+import androidx.fragment.app.Fragment
25
+import androidx.lifecycle.lifecycleScope
26
+import androidx.navigation.fragment.findNavController
27
+import androidx.viewpager2.widget.ViewPager2
28
+import com.certified.audionote.R
29
+import com.certified.audionote.adapter.ViewPagerAdapter
30
+import com.certified.audionote.databinding.FragmentOnboardingBinding
31
+import com.certified.audionote.model.SliderItem
32
+import com.certified.audionote.utils.Extensions.dataStore
33
+import com.certified.audionote.utils.Extensions.safeNavigate
34
+import com.certified.audionote.utils.PreferenceKeys
35
+import kotlinx.coroutines.launch
36
+
37
+class OnboardingFragment : Fragment() {
38
+
39
+    private var _binding: FragmentOnboardingBinding? = null
40
+    private val binding get() = _binding!!
41
+    private lateinit var sliderItem: ArrayList<SliderItem>
42
+
43
+    override fun onCreateView(
44
+        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
45
+    ): View {
46
+        // Inflate the layout for this fragment
47
+        _binding = FragmentOnboardingBinding.inflate(layoutInflater, container, false)
48
+        return binding.root
49
+    }
50
+
51
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
52
+        super.onViewCreated(view, savedInstanceState)
53
+
54
+        setUpSliderItem()
55
+        setUpViewPager()
56
+
57
+        binding.btnGetStarted.setOnClickListener {
58
+            lifecycleScope.launch {
59
+                requireContext().dataStore.edit {
60
+                    it[PreferenceKeys.FIRST_TIME_LOGIN] = false
61
+                }
62
+                findNavController().safeNavigate(OnboardingFragmentDirections.actionOnboardingFragmentToHomeFragment())
63
+            }
64
+        }
65
+    }
66
+
67
+    override fun onDestroyView() {
68
+        super.onDestroyView()
69
+        _binding = null
70
+    }
71
+
72
+    private fun setUpSliderItem() {
73
+        sliderItem = ArrayList()
74
+        sliderItem.add(
75
+            SliderItem(
76
+                R.drawable.ic_undraw_empty,
77
+                getString(R.string.view_pager_title_audio_recording),
78
+                getString(R.string.view_pager_description_audio_recording)
79
+            )
80
+        )
81
+        sliderItem.add(
82
+            SliderItem(
83
+                R.drawable.ic_undraw_empty,
84
+                getString(R.string.view_pager_title_notification),
85
+                getString(R.string.view_pager_description_notification)
86
+            )
87
+        )
88
+        sliderItem.add(
89
+            SliderItem(
90
+                R.drawable.ic_undraw_empty,
91
+                getString(R.string.view_pager_title_dark_mode),
92
+                getString(R.string.view_pager_description_dark_mode)
93
+            )
94
+        )
95
+    }
96
+
97
+    private fun setUpViewPager() {
98
+        val viewPagerAdapter = ViewPagerAdapter()
99
+        viewPagerAdapter.submitList(sliderItem)
100
+        binding.viewPager.adapter = viewPagerAdapter
101
+        binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
102
+            override fun onPageSelected(position: Int) {
103
+                super.onPageSelected(position)
104
+                binding.indicator.selection = position
105
+                if (position == sliderItem.size - 1) {
106
+                    binding.indicator.count = sliderItem.size
107
+                    binding.indicator.selection = position
108
+                }
109
+            }
110
+        })
111
+    }
112
+}
0 113
\ No newline at end of file
1 114
new file mode 100644
... ...
@@ -0,0 +1,62 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui
18
+
19
+import android.content.SharedPreferences
20
+import android.os.Bundle
21
+import androidx.appcompat.app.AppCompatDelegate
22
+import androidx.preference.PreferenceFragmentCompat
23
+import androidx.preference.PreferenceManager
24
+import com.certified.audionote.R
25
+
26
+class PreferenceFragment : PreferenceFragmentCompat(),
27
+    SharedPreferences.OnSharedPreferenceChangeListener {
28
+
29
+    override fun onCreate(savedInstanceState: Bundle?) {
30
+        super.onCreate(savedInstanceState)
31
+
32
+        PreferenceManager.getDefaultSharedPreferences(requireContext())
33
+            .registerOnSharedPreferenceChangeListener(this)
34
+    }
35
+
36
+    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
37
+        setPreferencesFromResource(R.xml.root_preferences, rootKey)
38
+    }
39
+
40
+    override fun onSharedPreferenceChanged(
41
+        sharedPreferences: SharedPreferences?,
42
+        key: String?
43
+    ) {
44
+        val darkModePreference = getString(R.string.key_theme)
45
+        key?.let {
46
+            if (it == darkModePreference) sharedPreferences?.let { pref ->
47
+                val darkModeValues = resources.getStringArray(R.array.pref_theme_values)
48
+                when (pref.getString(darkModePreference, darkModeValues[0])) {
49
+                    darkModeValues[0] -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
50
+                    darkModeValues[1] -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
51
+                    darkModeValues[2] -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
52
+                }
53
+            }
54
+        }
55
+    }
56
+
57
+    override fun onDestroyView() {
58
+        super.onDestroyView()
59
+        PreferenceManager.getDefaultSharedPreferences(requireContext())
60
+            .unregisterOnSharedPreferenceChangeListener(this)
61
+    }
62
+}
0 63
\ No newline at end of file
1 64
new file mode 100644
... ...
@@ -0,0 +1,138 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui.main
18
+
19
+import android.Manifest
20
+import android.app.*
21
+import android.content.*
22
+import android.content.pm.*
23
+import android.media.*
24
+import android.os.*
25
+import androidx.activity.*
26
+import androidx.activity.result.contract.*
27
+import androidx.appcompat.app.*
28
+import androidx.core.content.*
29
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
30
+import androidx.lifecycle.*
31
+import androidx.navigation.*
32
+import androidx.navigation.fragment.*
33
+import androidx.preference.*
34
+import com.certified.audionote.R
35
+import com.certified.audionote.databinding.*
36
+import com.certified.audionote.utils.*
37
+import com.certified.audionote.utils.Extensions.dataStore
38
+import com.google.android.material.dialog.*
39
+import dagger.hilt.android.*
40
+import kotlinx.coroutines.*
41
+import kotlinx.coroutines.flow.*
42
+
43
+@AndroidEntryPoint
44
+class MainActivity : AppCompatActivity() {
45
+    
46
+    private var _binding: ActivityMainBinding? = null
47
+    private val binding get() = _binding!!
48
+    private val viewModel: MainViewModel by viewModels()
49
+    private lateinit var navController: NavController
50
+    
51
+    private val requestNotificationPermissionLauncher =
52
+        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
53
+            if (!isGranted) MaterialAlertDialogBuilder(this).apply {
54
+                setTitle(getString(R.string.notification_permission))
55
+                setMessage(getString(R.string.notification_permission_required))
56
+                setPositiveButton(getString(R.string.ok)) { dialog, _ -> dialog.dismiss() }
57
+                show()
58
+            }
59
+        }
60
+    
61
+    override fun onCreate(savedInstanceState: Bundle?) {
62
+        super.onCreate(savedInstanceState)
63
+        
64
+        val splashScreen = installSplashScreen()
65
+        _binding = ActivityMainBinding.inflate(layoutInflater)
66
+        setContentView(binding.root)
67
+
68
+        val navHostFragment =
69
+            supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
70
+        navController = navHostFragment.navController
71
+
72
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
73
+            val notificationManager =
74
+                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
75
+            val defaultSoundUri =
76
+                RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
77
+            val audioAttributes =
78
+                AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
79
+                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build()
80
+            val channel = NotificationChannel(
81
+                getString(R.string.channelId),
82
+                getString(R.string.app_name),
83
+                NotificationManager.IMPORTANCE_DEFAULT
84
+            )
85
+            channel.enableVibration(true)
86
+            channel.vibrationPattern = longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
87
+            channel.setSound(defaultSoundUri, audioAttributes)
88
+            notificationManager.createNotificationChannel(channel)
89
+        }
90
+
91
+        isDarkModeEnabled()
92
+        checkNotificationPermission()
93
+        splashScreen.setKeepOnScreenCondition { viewModel.isLoading.value }
94
+        lifecycleScope.launch(Dispatchers.Main) {
95
+            this@MainActivity.dataStore.data.map { it[PreferenceKeys.FIRST_TIME_LOGIN] }.collect {
96
+                if (it != null) navController.navigate(R.id.homeFragment)
97
+            }
98
+        }
99
+    }
100
+    
101
+    private fun isDarkModeEnabled() {
102
+        val darkModePreference = getString(R.string.key_theme)
103
+        val darkModeValues = resources.getStringArray(R.array.pref_theme_values)
104
+        val preferences = PreferenceManager.getDefaultSharedPreferences(this)
105
+        when (preferences.getString(darkModePreference, darkModeValues[0])) {
106
+            darkModeValues[0] -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
107
+            darkModeValues[1] -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
108
+            darkModeValues[2] -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
109
+        }
110
+    }
111
+    
112
+    private fun checkNotificationPermission() {
113
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
114
+            if (ContextCompat.checkSelfPermission(
115
+                    this, Manifest.permission.POST_NOTIFICATIONS
116
+                ) == PackageManager.PERMISSION_GRANTED
117
+            ) {
118
+                // FCM SDK (and your app) can post notifications.
119
+            } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS))
120
+                MaterialAlertDialogBuilder(this).apply {
121
+                    setTitle(getString(R.string.notification_permission))
122
+                    setMessage(getString(R.string.notification_permission_required))
123
+                    setPositiveButton(getString(R.string.ok)) { dialog, _ -> dialog.dismiss() }
124
+                    show()
125
+                }
126
+            else
127
+                requestNotificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
128
+        }
129
+    }
130
+    
131
+    private suspend fun isFirstLogin() {
132
+    }
133
+    
134
+    override fun onDestroy() {
135
+        super.onDestroy()
136
+        _binding = null
137
+    }
138
+}
0 139
\ No newline at end of file
1 140
new file mode 100644
... ...
@@ -0,0 +1,23 @@
1
+package com.certified.audionote.ui.main
2
+
3
+import androidx.lifecycle.ViewModel
4
+import androidx.lifecycle.viewModelScope
5
+import dagger.hilt.android.lifecycle.HiltViewModel
6
+import kotlinx.coroutines.delay
7
+import kotlinx.coroutines.flow.MutableStateFlow
8
+import kotlinx.coroutines.flow.asStateFlow
9
+import kotlinx.coroutines.launch
10
+
11
+//@HiltViewModel
12
+class MainViewModel : ViewModel() {
13
+
14
+    private val _isLoading = MutableStateFlow(true)
15
+    val isLoading = _isLoading.asStateFlow()
16
+
17
+    init {
18
+        viewModelScope.launch {
19
+            delay(1000L)
20
+            _isLoading.value = false
21
+        }
22
+    }
23
+}
0 24
\ No newline at end of file
1 25
new file mode 100644
... ...
@@ -0,0 +1,69 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui.theme
18
+
19
+import androidx.compose.foundation.*
20
+import androidx.compose.runtime.*
21
+import androidx.compose.ui.graphics.*
22
+
23
+/**
24
+ * Created by MJ Jacobs on 2024/12/28 at 13:07
25
+ */
26
+
27
+//  Light colors
28
+val purple200 = Color(0xFFBB86FC)
29
+val purple500 = Color(0xFF6200EE)
30
+val purple700 = Color(0xFF3700B3)
31
+val teal200 = Color(0xFF03DAC5)
32
+val teal700 = Color(0xFF018786)
33
+val black = Color(0xFF000000)
34
+val white = Color(0xFFFFFFFF)
35
+
36
+val accentLight = Color(0xFFFFECF1)
37
+val fragment_background = accentLight
38
+val other_fragment_background = Color(0xFF986977)
39
+val primaryLight = Color(0xFFEFB8C8)
40
+val primaryDarkLight = Color(0xFFD29DAC)
41
+val primaryDarkerLight = Color(0xFF986977)
42
+val micAccentLight = Color(0xFF939094)
43
+val fabBackgroundTintLight = primaryLight
44
+val aboutIconColorLight = Color(0xFFEFB8C8)
45
+val editReminderButtonColorLight = other_fragment_background
46
+val greyLight = Color(0xFFAEAEAE)
47
+val titleTextLight = primaryDarkerLight
48
+val subtitleTextLight = primaryDarkLight
49
+
50
+//  Dark colors
51
+val primaryDark = Color(0xFF313033)
52
+val primaryDarkDark = Color(0xFF1C1B1F)
53
+val primaryDarkerDark = black
54
+val accentDark = white
55
+val fragmentBackgroundDark = primaryDark
56
+val otherFragmentBackgroundDark = primaryDarkerDark
57
+val micAccentDark = Color(0xFF939094)
58
+val fabBackgroundTintDark = Color(0xFFEFB8C8)
59
+val aboutIconColorDark = Color(0xFF939094)
60
+val editReminderButtonColorDark = aboutIconColorDark
61
+val greyDark = white
62
+val titleTextDark = white
63
+val subtitleTextDark = white
64
+
65
+@Composable
66
+fun dayNightBackgroundColor(): Color = if (isSystemInDarkTheme()) black else white
67
+
68
+@Composable
69
+fun statusBarColor(): Color = if (isSystemInDarkTheme()) primaryDarkDark else primaryDarkLight
0 70
\ No newline at end of file
1 71
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui.theme
18
+
19
+import androidx.compose.ui.unit.*
20
+
21
+/**
22
+ * Created by MJ Jacobs on 2024/12/28 at 13:28
23
+ */
24
+
25
+val largePadding = 32.dp
26
+val normalPadding = 16.dp
27
+val halfPadding = 8.dp
28
+val smallPadding = 4.dp
29
+
30
+val defaultCornerSize = 15.dp
0 31
\ No newline at end of file
1 32
new file mode 100644
... ...
@@ -0,0 +1,56 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui.theme
18
+
19
+import androidx.compose.foundation.*
20
+import androidx.compose.material3.*
21
+import androidx.compose.runtime.*
22
+import androidx.compose.ui.*
23
+
24
+/**
25
+ * Created by MJ Jacobs on 2024/12/28 at 13:20
26
+ */
27
+
28
+val DarkColor = darkColorScheme(
29
+    primary = primaryDark,
30
+    secondary = primaryDarkDark,
31
+    tertiary = primaryDarkerDark,
32
+    onPrimary = accentDark,
33
+    onSecondary = black
34
+)
35
+
36
+val LightColor = lightColorScheme(
37
+    primary = primaryLight,
38
+    secondary = primaryDarkLight,
39
+    tertiary = primaryDarkerLight,
40
+    onPrimary = accentLight,
41
+    onSecondary = black
42
+)
43
+
44
+@Composable
45
+fun AudioNoteTheme(
46
+    isDarkTheme:Boolean = isSystemInDarkTheme(),
47
+    content: @Composable () -> Unit
48
+) {
49
+    val color = if (isDarkTheme) DarkColor else LightColor
50
+    
51
+    MaterialTheme(
52
+        colorScheme = color,
53
+        typography = typography,
54
+        content = content
55
+    )
56
+}
0 57
\ No newline at end of file
1 58
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.ui.theme
18
+
19
+import androidx.compose.material3.Typography
20
+
21
+/**
22
+ * Created by MJ Jacobs on 2024/12/28 at 13:24
23
+ */
24
+
25
+//  Setting material theme typography
26
+val typography = Typography(
27
+    /** Other default text styles to override
28
+     *  titleLarge = TextStyle(
29
+     *      fontFamily = FontFamily.Default,
30
+     *      fontWeight = FontWeight.Normal,
31
+     *      fontSize = 22.sp,
32
+     *      lineHeight = 28.sp,
33
+     *      letterSpacing = 0.sp
34
+     *      ),
35
+     *  labelSmall = TextStyle(
36
+     *      fontFamily = FontFamily.Default,
37
+     *      fontWeight = FontWeight.Medium,
38
+     *      fontSize = 11.sp,
39
+     *      lineHeight = 16.sp,
40
+     *      letterSpacing = 0.5.sp
41
+     *      )
42
+    */
43
+)
0 44
\ No newline at end of file
1 45
new file mode 100644
... ...
@@ -0,0 +1,28 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+import androidx.room.TypeConverter
20
+import java.util.*
21
+
22
+class Converters {
23
+    @TypeConverter
24
+    fun fromTimeStamp(value: Long) = Date(value)
25
+
26
+    @TypeConverter
27
+    fun dateToTimeStamp(date: Date) = date.time
28
+}
0 29
\ No newline at end of file
1 30
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+enum class UIState {
20
+    LOADING,
21
+    HAS_DATA,
22
+    EMPTY
23
+}
24
+
25
+enum class ReminderAvailableState {
26
+    HAS_REMINDER,
27
+    NO_REMINDER
28
+}
29
+
30
+enum class ReminderCompletionState {
31
+    COMPLETED,
32
+    ONGOING
33
+}
0 34
\ No newline at end of file
1 35
new file mode 100644
... ...
@@ -0,0 +1,72 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+import android.app.Activity
20
+import android.content.Context
21
+import android.os.Bundle
22
+import android.view.View
23
+import android.view.WindowManager
24
+import android.view.inputmethod.InputMethodManager
25
+import android.widget.Toast
26
+import androidx.annotation.IdRes
27
+import androidx.core.content.res.ResourcesCompat
28
+import androidx.datastore.preferences.preferencesDataStore
29
+import androidx.fragment.app.Fragment
30
+import androidx.navigation.NavController
31
+import androidx.navigation.NavDirections
32
+
33
+object Extensions {
34
+    fun Fragment.flags(color: Int) {
35
+        val window = requireActivity().window
36
+        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
37
+//        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
38
+        window.statusBarColor = ResourcesCompat.getColor(resources, color, null)
39
+    }
40
+
41
+    fun Fragment.showToast(message: String) {
42
+        Toast.makeText(
43
+            requireContext(),
44
+            message,
45
+            Toast.LENGTH_LONG
46
+        ).show()
47
+    }
48
+
49
+    val Context.dataStore by preferencesDataStore(name = "com.certified.audionotes.preferences")
50
+
51
+    fun View.hideKeyboardFrom(context: Context) {
52
+        val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
53
+        imm.hideSoftInputFromWindow(windowToken, 0)
54
+    }
55
+
56
+    fun View.showKeyboardFor(context: Context) {
57
+        val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
58
+        imm.showSoftInput(this, 0)
59
+    }
60
+
61
+    fun NavController.safeNavigate(direction: NavDirections) {
62
+        currentDestination?.getAction(direction.actionId)?.run { navigate(direction) }
63
+    }
64
+
65
+    fun NavController.safeNavigate(
66
+        @IdRes currentDestinationId: Int,
67
+        @IdRes id: Int,
68
+        args: Bundle? = null
69
+    ) {
70
+        if (currentDestinationId == currentDestination?.id) navigate(id, args)
71
+    }
72
+}
0 73
\ No newline at end of file
1 74
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+fun main() {
20
+    val i = "00:08:18"
21
+    val time = i.filter { it.isDigit() }.toLong()
22
+    val sec = time % 60
23
+    val minute = (time % 3600) / 60
24
+    println("Time: $time, Minute: $minute, Second: $sec")
25
+//    print(isEven(201))
26
+}
27
+
28
+fun isEven(number: Int): String {
29
+    return when (number % 2) {
30
+        0 -> "true"
31
+        else -> "false"
32
+    }
33
+}
0 34
\ No newline at end of file
1 35
new file mode 100644
... ...
@@ -0,0 +1,101 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+import android.app.NotificationManager
20
+import android.content.Context
21
+import android.media.RingtoneManager
22
+import android.os.Build
23
+import androidx.core.app.NotificationCompat
24
+import androidx.core.app.NotificationCompat.DEFAULT_ALL
25
+import androidx.core.app.NotificationCompat.PRIORITY_HIGH
26
+import androidx.core.content.res.ResourcesCompat
27
+import androidx.navigation.NavDeepLinkBuilder
28
+import androidx.work.Worker
29
+import androidx.work.WorkerParameters
30
+import com.certified.audionote.R
31
+import com.certified.audionote.model.Note
32
+import com.certified.audionote.ui.EditNoteFragmentArgs
33
+import com.certified.audionote.ui.main.MainActivity
34
+
35
+class NotificationWorker(private val appContext: Context, workerParams: WorkerParameters) :
36
+    Worker(appContext, workerParams) {
37
+    override fun doWork(): Result {
38
+
39
+        val noteId = inputData.getInt("noteId", 0)
40
+        val noteTitle = inputData.getString("noteTitle")
41
+        val noteDescription = inputData.getString("noteDescription")
42
+        val noteColor = inputData.getInt("noteColor", -1)
43
+        val noteLastModificationDate = inputData.getLong("noteLastModificationDate", -1L)
44
+        val noteSize = inputData.getString("noteSize")
45
+        val noteAudioLength = inputData.getLong("noteAudioLength", 0L)
46
+        val noteFilePath = inputData.getString("noteFilePath")
47
+        val noteStarted = inputData.getBoolean("noteStarted", false)
48
+        val noteReminder = inputData.getLong("noteReminder", -1L)
49
+
50
+        val note = Note(
51
+            noteTitle!!,
52
+            noteDescription!!,
53
+            noteColor,
54
+            noteLastModificationDate,
55
+            noteSize!!,
56
+            noteAudioLength,
57
+            noteFilePath!!,
58
+            noteStarted,
59
+            noteReminder,
60
+            noteId,
61
+        )
62
+        notifyUser(appContext, note)
63
+
64
+        return Result.success()
65
+    }
66
+
67
+    private fun notifyUser(context: Context, note: Note) {
68
+
69
+        val defaultSoundUri =
70
+            RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
71
+        val notificationManager =
72
+            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
73
+
74
+        val pendingIntent =
75
+            NavDeepLinkBuilder(context)
76
+                .setGraph(R.navigation.navigation)
77
+                .setDestination(
78
+                    R.id.editNoteFragment,
79
+                    EditNoteFragmentArgs(note).toBundle()
80
+                )
81
+                .setComponentName(MainActivity::class.java)
82
+                .createPendingIntent()
83
+
84
+        val notificationBuilder =
85
+            NotificationCompat.Builder(context, context.getString(R.string.channelId))
86
+                .setSmallIcon(R.drawable.ic_baseline_notifications_24)
87
+                .setContentTitle(note.title)
88
+                .setContentText("Hi there, it's time to check out ${note.title}")
89
+                .setColor(ResourcesCompat.getColor(context.resources, R.color.primary, null))
90
+                .setSound(defaultSoundUri)
91
+                .setDefaults(DEFAULT_ALL)
92
+                .setContentIntent(pendingIntent)
93
+                .setPriority(PRIORITY_HIGH)
94
+                .setAutoCancel(true)
95
+
96
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
97
+            notificationBuilder.setChannelId(context.getString(R.string.channelId))
98
+
99
+        notificationManager.notify(note.id, notificationBuilder.build())
100
+    }
101
+}
0 102
\ No newline at end of file
1 103
new file mode 100644
... ...
@@ -0,0 +1,23 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+import androidx.datastore.preferences.core.booleanPreferencesKey
20
+
21
+object PreferenceKeys {
22
+    val FIRST_TIME_LOGIN = booleanPreferencesKey("FIRST_TIME_LOGIN")
23
+}
0 24
\ No newline at end of file
1 25
new file mode 100644
... ...
@@ -0,0 +1,113 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+import android.app.Activity
20
+import android.app.AlarmManager
21
+import android.app.PendingIntent
22
+import android.content.Context
23
+import android.content.Intent
24
+import android.os.Build
25
+import android.util.Log
26
+import com.certified.audionote.R
27
+import com.certified.audionote.model.Note
28
+import com.certified.audionote.ui.AlertReceiver
29
+import java.text.SimpleDateFormat
30
+import java.util.Calendar
31
+import java.util.Date
32
+import java.util.Locale
33
+import java.util.concurrent.TimeUnit
34
+
35
+val colors = listOf(
36
+    -504764, -740056, -1544140, -2277816, -3246217, -4024195,
37
+    -4224594, -7305542, -7551917, -7583749, -10712898, -10896368, -10965321,
38
+    -11419154, -14654801
39
+)
40
+
41
+fun filePath(activity: Activity) = activity.getExternalFilesDir("/")?.absolutePath
42
+
43
+fun currentDate(): Calendar = Calendar.getInstance()
44
+
45
+fun formatDate(date: Long, context: Context): String {
46
+
47
+    val now = Date()
48
+    val seconds = TimeUnit.MILLISECONDS.toSeconds(now.time - date)
49
+    val minutes = TimeUnit.MILLISECONDS.toMinutes(now.time - date)
50
+    val hours = TimeUnit.MILLISECONDS.toHours(now.time - date)
51
+    val days = TimeUnit.MILLISECONDS.toDays(now.time - date)
52
+
53
+    return when {
54
+        seconds < 60 -> context.getString(R.string.just_now)
55
+        minutes == 1L -> context.getString(R.string.a_minute_ago)
56
+        minutes in 2..59L -> "$minutes ${context.getString(R.string.minutes_ago)}"
57
+        hours == 1L -> context.getString(R.string.an_hour_ago)
58
+        hours in 2..23 -> "$hours ${context.getString(R.string.hours_ago)}"
59
+        days == 1L -> context.getString(R.string.a_day_ago)
60
+        else -> formatSimpleDate(date)
61
+    }
62
+}
63
+
64
+fun formatReminderDate(date: Long): String =
65
+    SimpleDateFormat("dd MMM, yyyy h:mm a", Locale.getDefault()).format(date)
66
+
67
+fun formatSimpleDate(date: Long): String =
68
+    SimpleDateFormat("dd/MM/yy", Locale.getDefault()).format(date)
69
+
70
+fun formatDateOnly(date: Long): String =
71
+    SimpleDateFormat("dd MMM, yyyy", Locale.getDefault()).format(date)
72
+
73
+fun formatTime(date: Long): String = SimpleDateFormat("h:mm a", Locale.getDefault()).format(date)
74
+
75
+fun startAlarm(context: Context, time: Long, note: Note) {
76
+    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
77
+    val intent = Intent(context, AlertReceiver::class.java)
78
+    intent.apply {
79
+        putExtra("noteId", note.id)
80
+        putExtra("noteTitle", note.title)
81
+        putExtra("noteDescription", note.description)
82
+        putExtra("noteColor", note.color)
83
+        putExtra("noteLastModificationDate", note.lastModificationDate)
84
+        putExtra("noteSize", note.size)
85
+        putExtra("noteAudioLength", note.audioLength)
86
+        putExtra("noteFilePath", note.filePath)
87
+        putExtra("noteStarted", note.started)
88
+        putExtra("noteReminder", note.reminder)
89
+    }
90
+    val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
91
+        PendingIntent.getBroadcast(context, note.id, intent, PendingIntent.FLAG_IMMUTABLE)
92
+    } else {
93
+        PendingIntent.getBroadcast(context, note.id, intent, 0)
94
+    }
95
+    alarmManager.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent)
96
+    Log.d("TAG", "startAlarm: Alarm started")
97
+}
98
+
99
+fun cancelAlarm(context: Context, noteId: Int) {
100
+    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
101
+    val intent = Intent(context, AlertReceiver::class.java)
102
+    val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
103
+        PendingIntent.getBroadcast(context, noteId, intent, PendingIntent.FLAG_IMMUTABLE)
104
+    } else {
105
+        PendingIntent.getBroadcast(context, noteId, intent, 0)
106
+    }
107
+    alarmManager.cancel(pendingIntent)
108
+    Log.d("TAG", "cancelAlarm: Alarm canceled")
109
+}
110
+
111
+fun roundOffDecimal(number: Double): String {
112
+    return "%.2f".format(number)
113
+}
0 114
\ No newline at end of file
1 115
new file mode 100644
... ...
@@ -0,0 +1,77 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote.utils
18
+
19
+import android.app.Activity
20
+import androidx.compose.runtime.*
21
+import androidx.window.layout.*
22
+
23
+/**
24
+ * Created by MJ Jacobs on 2024/12/28 at 14:04
25
+ */
26
+
27
+@Composable
28
+fun calculateWindowSize(
29
+    activity: Activity,
30
+    windowWidthSizeClassChange: @Composable (windowSize: WindowSizeClass) -> Unit = {},
31
+    windowHeightSizeClassChange: @Composable (windowSize: WindowSizeClass) -> Unit = {},
32
+) {
33
+    val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)
34
+    
35
+    val widthDp = metrics.bounds.width() / activity.resources.displayMetrics.density
36
+    val heightDp = metrics.bounds.height() / activity.resources.displayMetrics.density
37
+    
38
+    when {
39
+        widthDp < 600f -> {
40
+            //  99.96% of phones in portrait
41
+            windowWidthSizeClassChange(WindowSizeClass.COMPACT)
42
+        }
43
+        
44
+        widthDp < 840f -> {
45
+            //  93.73% of tablets in portrait
46
+            windowWidthSizeClassChange(WindowSizeClass.MEDIUM)
47
+        }
48
+        
49
+        else -> {
50
+            //  97.22% of tablets in landscape
51
+            windowWidthSizeClassChange(WindowSizeClass.EXPANDED)
52
+        }
53
+    }
54
+    
55
+    when {
56
+        heightDp < 480f -> {
57
+            //  99.78 of phones in landscape
58
+            windowHeightSizeClassChange(WindowSizeClass.COMPACT)
59
+        }
60
+        
61
+        heightDp < 900f -> {
62
+            //  96.56% of tablets in landscape and 97.59% of phones in portrait
63
+            windowHeightSizeClassChange(WindowSizeClass.MEDIUM)
64
+        }
65
+        
66
+        else -> {
67
+            //  94.25% of tablets in portrait
68
+            windowHeightSizeClassChange(WindowSizeClass.EXPANDED)
69
+        }
70
+    }
71
+}
72
+
73
+enum class WindowSizeClass {
74
+    COMPACT,
75
+    MEDIUM,
76
+    EXPANDED
77
+}
0 78
\ No newline at end of file
1 79
new file mode 100644
... ...
@@ -0,0 +1,31 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<set xmlns:android="http://schemas.android.com/apk/res/android">
18
+
19
+    <alpha
20
+        android:duration="300"
21
+        android:fromAlpha="0"
22
+        android:toAlpha="1" />
23
+    <scale
24
+        android:duration="300"
25
+        android:pivotX="50%"
26
+        android:pivotY="50%"
27
+        android:fromXScale="40%"
28
+        android:fromYScale="40%"
29
+        android:toXScale="100%"
30
+        android:toYScale="100%" />
31
+</set>
0 32
\ No newline at end of file
1 33
new file mode 100644
... ...
@@ -0,0 +1,31 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<set xmlns:android="http://schemas.android.com/apk/res/android">
18
+
19
+    <alpha
20
+        android:duration="300"
21
+        android:fromAlpha="1"
22
+        android:toAlpha="0" />
23
+    <scale
24
+        android:duration="300"
25
+        android:pivotX="50%"
26
+        android:pivotY="50%"
27
+        android:fromXScale="100%"
28
+        android:fromYScale="100%"
29
+        android:toXScale="40%"
30
+        android:toYScale="40%" />
31
+</set>
0 32
\ No newline at end of file
1 33
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<set xmlns:android="http://schemas.android.com/apk/res/android">
18
+    <translate
19
+        android:duration="300"
20
+        android:fromXDelta="100%"
21
+        android:fromYDelta="0%"
22
+        android:toXDelta="0%"
23
+        android:toYDelta="0%" />
24
+</set>
0 25
\ No newline at end of file
1 26
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<set xmlns:android="http://schemas.android.com/apk/res/android">
18
+    <translate
19
+        android:duration="300"
20
+        android:fromXDelta="0%"
21
+        android:fromYDelta="0%"
22
+        android:toXDelta="100%"
23
+        android:toYDelta="0%" />
24
+</set>
0 25
\ No newline at end of file
1 26
new file mode 100644
... ...
@@ -0,0 +1,46 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:aapt="http://schemas.android.com/aapt"
19
+    android:width="108dp"
20
+    android:height="108dp"
21
+    android:viewportWidth="108"
22
+    android:viewportHeight="108">
23
+    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
24
+        <aapt:attr name="android:fillColor">
25
+            <gradient
26
+                android:endX="85.84757"
27
+                android:endY="92.4963"
28
+                android:startX="42.9492"
29
+                android:startY="49.59793"
30
+                android:type="linear">
31
+                <item
32
+                    android:color="#44000000"
33
+                    android:offset="0.0" />
34
+                <item
35
+                    android:color="#00000000"
36
+                    android:offset="1.0" />
37
+            </gradient>
38
+        </aapt:attr>
39
+    </path>
40
+    <path
41
+        android:fillColor="#FFFFFF"
42
+        android:fillType="nonZero"
43
+        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
44
+        android:strokeWidth="1"
45
+        android:strokeColor="#00000000" />
46
+</vector>
0 47
\ No newline at end of file
1 48
new file mode 100644
2 49
Binary files /dev/null and b/app/src/main/res/drawable/figma_logo.png differ
3 50
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M10.54,14.53L8.41,12.4l-1.06,1.06 3.18,3.18 6,-6 -1.06,-1.06zM17.337,1.81l4.607,3.845 -1.28,1.535 -4.61,-3.843zM6.663,1.81l1.282,1.536L3.337,7.19l-1.28,-1.536zM12,4c-4.97,0 -9,4.03 -9,9s4.03,9 9,9 9,-4.03 9,-9 -4.03,-9 -9,-9zM12,20c-3.86,0 -7,-3.14 -7,-7s3.14,-7 7,-7 7,3.14 7,7 -3.14,7 -7,7z"
24
+      android:fillColor="#000000"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M16.62,2.99c-0.49,-0.49 -1.28,-0.49 -1.77,0L6.54,11.3c-0.39,0.39 -0.39,1.02 0,1.41l8.31,8.31c0.49,0.49 1.28,0.49 1.77,0s0.49,-1.28 0,-1.77L9.38,12l7.25,-7.25c0.48,-0.48 0.48,-1.28 -0.01,-1.76z"
24
+      android:fillColor="@color/black_day_white_night"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,28 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="200dp"
19
+    android:height="200dp"
20
+    android:viewportWidth="200"
21
+    android:viewportHeight="200">
22
+  <path
23
+      android:pathData="M100,100m-100,0a100,100 0,1 1,200 0a100,100 0,1 1,-200 0"
24
+      android:fillColor="#939094"/>
25
+  <path
26
+      android:pathData="M70,74.86V125.14C70,128.974 75.145,131.304 79.108,129.217L127.25,104.077C130.917,102.184 130.917,97.816 127.25,95.875L79.108,70.783C75.145,68.696 70,71.026 70,74.86Z"
27
+      android:fillColor="#313033"/>
28
+</vector>
0 29
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="200dp"
19
+    android:height="200dp"
20
+    android:viewportWidth="200"
21
+    android:viewportHeight="200">
22
+  <path
23
+      android:pathData="M100,100m-98.5,0a98.5,98.5 0,1 1,197 0a98.5,98.5 0,1 1,-197 0"
24
+      android:strokeWidth="3"
25
+      android:fillColor="#00000000"
26
+      android:strokeColor="#EFB8C8"/>
27
+  <path
28
+      android:pathData="M100,100m-85,0a85,85 0,1 1,170 0a85,85 0,1 1,-170 0"
29
+      android:fillColor="#EFB8C8"/>
30
+  <path
31
+      android:pathData="M70,74.86V125.14C70,128.974 75.145,131.304 79.108,129.217L127.25,104.077C130.917,102.184 130.917,97.816 127.25,95.875L79.108,70.783C75.145,68.696 70,71.026 70,74.86Z"
32
+      android:fillColor="#ffffff"/>
33
+</vector>
0 34
new file mode 100644
... ...
@@ -0,0 +1,26 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24"
22
+    android:tint="?attr/colorControlNormal">
23
+  <path
24
+      android:fillColor="@android:color/white"
25
+      android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
26
+</vector>
0 27
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="24dp"
19
+    android:height="24dp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M20,8.69L20,4h-4.69L12,0.69 8.69,4L4,4v4.69L0.69,12 4,15.31L4,20h4.69L12,23.31 15.31,20L20,20v-4.69L23.31,12 20,8.69zM18,14.48L18,18h-3.52L12,20.48 9.52,18L6,18v-3.52L3.52,12 6,9.52L6,6h3.52L12,3.52 14.48,6L18,6v3.52L20.48,12 18,14.48zM12,6v12c3.31,0 6,-2.69 6,-6s-2.69,-6 -6,-6z"
24
+      android:fillColor="@color/black_day_white_night"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="24dp"
19
+    android:height="24dp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M8.7,15.9L4.8,12l3.9,-3.9c0.39,-0.39 0.39,-1.01 0,-1.4 -0.39,-0.39 -1.01,-0.39 -1.4,0l-4.59,4.59c-0.39,0.39 -0.39,1.02 0,1.41l4.59,4.6c0.39,0.39 1.01,0.39 1.4,0 0.39,-0.39 0.39,-1.01 0,-1.4zM15.3,15.9l3.9,-3.9 -3.9,-3.9c-0.39,-0.39 -0.39,-1.01 0,-1.4 0.39,-0.39 1.01,-0.39 1.4,0l4.59,4.59c0.39,0.39 0.39,1.02 0,1.41l-4.59,4.6c-0.39,0.39 -1.01,0.39 -1.4,0 -0.39,-0.39 -0.39,-1.01 0,-1.4z"
24
+      android:fillColor="@color/black_day_white_night"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="24dp"
19
+    android:height="24dp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M11,23.59v-3.6c-5.01,-0.26 -9,-4.42 -9,-9.49C2,5.26 6.26,1 11.5,1S21,5.26 21,10.5c0,4.95 -3.44,9.93 -8.57,12.4l-1.43,0.69zM11.5,3C7.36,3 4,6.36 4,10.5S7.36,18 11.5,18L13,18v2.3c3.64,-2.3 6,-6.08 6,-9.8C19,6.36 15.64,3 11.5,3zM10.5,14.5h2v2h-2zM12.5,13h-2c0,-3.25 3,-3 3,-5 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2h-2c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,2.5 -3,2.75 -3,5z"
24
+      android:fillColor="@color/black_day_white_night"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M16,9v10H8V9h8m-1.5,-6h-5l-1,1H5v2h14V4h-3.5l-1,-1zM18,7H6v12c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7z"
24
+      android:fillColor="#000000"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M9,16.2l-3.5,-3.5c-0.39,-0.39 -1.01,-0.39 -1.4,0 -0.39,0.39 -0.39,1.01 0,1.4l4.19,4.19c0.39,0.39 1.02,0.39 1.41,0L20.3,7.7c0.39,-0.39 0.39,-1.01 0,-1.4 -0.39,-0.39 -1.01,-0.39 -1.4,0L9,16.2z"
24
+      android:fillColor="#000000"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="24dp"
19
+    android:height="24dp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"
24
+      android:fillColor="@color/black_day_white_night"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,186 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
19
+    android:width="108dp"
20
+    android:height="108dp"
21
+    android:viewportWidth="108"
22
+    android:viewportHeight="108">
23
+    <path
24
+        android:fillColor="#3DDC84"
25
+        android:pathData="M0,0h108v108h-108z" />
26
+    <path
27
+        android:fillColor="#00000000"
28
+        android:pathData="M9,0L9,108"
29
+        android:strokeWidth="0.8"
30
+        android:strokeColor="#33FFFFFF" />
31
+    <path
32
+        android:fillColor="#00000000"
33
+        android:pathData="M19,0L19,108"
34
+        android:strokeWidth="0.8"
35
+        android:strokeColor="#33FFFFFF" />
36
+    <path
37
+        android:fillColor="#00000000"
38
+        android:pathData="M29,0L29,108"
39
+        android:strokeWidth="0.8"
40
+        android:strokeColor="#33FFFFFF" />
41
+    <path
42
+        android:fillColor="#00000000"
43
+        android:pathData="M39,0L39,108"
44
+        android:strokeWidth="0.8"
45
+        android:strokeColor="#33FFFFFF" />
46
+    <path
47
+        android:fillColor="#00000000"
48
+        android:pathData="M49,0L49,108"
49
+        android:strokeWidth="0.8"
50
+        android:strokeColor="#33FFFFFF" />
51
+    <path
52
+        android:fillColor="#00000000"
53
+        android:pathData="M59,0L59,108"
54
+        android:strokeWidth="0.8"
55
+        android:strokeColor="#33FFFFFF" />
56
+    <path
57
+        android:fillColor="#00000000"
58
+        android:pathData="M69,0L69,108"
59
+        android:strokeWidth="0.8"
60
+        android:strokeColor="#33FFFFFF" />
61
+    <path
62
+        android:fillColor="#00000000"
63
+        android:pathData="M79,0L79,108"
64
+        android:strokeWidth="0.8"
65
+        android:strokeColor="#33FFFFFF" />
66
+    <path
67
+        android:fillColor="#00000000"
68
+        android:pathData="M89,0L89,108"
69
+        android:strokeWidth="0.8"
70
+        android:strokeColor="#33FFFFFF" />
71
+    <path
72
+        android:fillColor="#00000000"
73
+        android:pathData="M99,0L99,108"
74
+        android:strokeWidth="0.8"
75
+        android:strokeColor="#33FFFFFF" />
76
+    <path
77
+        android:fillColor="#00000000"
78
+        android:pathData="M0,9L108,9"
79
+        android:strokeWidth="0.8"
80
+        android:strokeColor="#33FFFFFF" />
81
+    <path
82
+        android:fillColor="#00000000"
83
+        android:pathData="M0,19L108,19"
84
+        android:strokeWidth="0.8"
85
+        android:strokeColor="#33FFFFFF" />
86
+    <path
87
+        android:fillColor="#00000000"
88
+        android:pathData="M0,29L108,29"
89
+        android:strokeWidth="0.8"
90
+        android:strokeColor="#33FFFFFF" />
91
+    <path
92
+        android:fillColor="#00000000"
93
+        android:pathData="M0,39L108,39"
94
+        android:strokeWidth="0.8"
95
+        android:strokeColor="#33FFFFFF" />
96
+    <path
97
+        android:fillColor="#00000000"
98
+        android:pathData="M0,49L108,49"
99
+        android:strokeWidth="0.8"
100
+        android:strokeColor="#33FFFFFF" />
101
+    <path
102
+        android:fillColor="#00000000"
103
+        android:pathData="M0,59L108,59"
104
+        android:strokeWidth="0.8"
105
+        android:strokeColor="#33FFFFFF" />
106
+    <path
107
+        android:fillColor="#00000000"
108
+        android:pathData="M0,69L108,69"
109
+        android:strokeWidth="0.8"
110
+        android:strokeColor="#33FFFFFF" />
111
+    <path
112
+        android:fillColor="#00000000"
113
+        android:pathData="M0,79L108,79"
114
+        android:strokeWidth="0.8"
115
+        android:strokeColor="#33FFFFFF" />
116
+    <path
117
+        android:fillColor="#00000000"
118
+        android:pathData="M0,89L108,89"
119
+        android:strokeWidth="0.8"
120
+        android:strokeColor="#33FFFFFF" />
121
+    <path
122
+        android:fillColor="#00000000"
123
+        android:pathData="M0,99L108,99"
124
+        android:strokeWidth="0.8"
125
+        android:strokeColor="#33FFFFFF" />
126
+    <path
127
+        android:fillColor="#00000000"
128
+        android:pathData="M19,29L89,29"
129
+        android:strokeWidth="0.8"
130
+        android:strokeColor="#33FFFFFF" />
131
+    <path
132
+        android:fillColor="#00000000"
133
+        android:pathData="M19,39L89,39"
134
+        android:strokeWidth="0.8"
135
+        android:strokeColor="#33FFFFFF" />
136
+    <path
137
+        android:fillColor="#00000000"
138
+        android:pathData="M19,49L89,49"
139
+        android:strokeWidth="0.8"
140
+        android:strokeColor="#33FFFFFF" />
141
+    <path
142
+        android:fillColor="#00000000"
143
+        android:pathData="M19,59L89,59"
144
+        android:strokeWidth="0.8"
145
+        android:strokeColor="#33FFFFFF" />
146
+    <path
147
+        android:fillColor="#00000000"
148
+        android:pathData="M19,69L89,69"
149
+        android:strokeWidth="0.8"
150
+        android:strokeColor="#33FFFFFF" />
151
+    <path
152
+        android:fillColor="#00000000"
153
+        android:pathData="M19,79L89,79"
154
+        android:strokeWidth="0.8"
155
+        android:strokeColor="#33FFFFFF" />
156
+    <path
157
+        android:fillColor="#00000000"
158
+        android:pathData="M29,19L29,89"
159
+        android:strokeWidth="0.8"
160
+        android:strokeColor="#33FFFFFF" />
161
+    <path
162
+        android:fillColor="#00000000"
163
+        android:pathData="M39,19L39,89"
164
+        android:strokeWidth="0.8"
165
+        android:strokeColor="#33FFFFFF" />
166
+    <path
167
+        android:fillColor="#00000000"
168
+        android:pathData="M49,19L49,89"
169
+        android:strokeWidth="0.8"
170
+        android:strokeColor="#33FFFFFF" />
171
+    <path
172
+        android:fillColor="#00000000"
173
+        android:pathData="M59,19L59,89"
174
+        android:strokeWidth="0.8"
175
+        android:strokeColor="#33FFFFFF" />
176
+    <path
177
+        android:fillColor="#00000000"
178
+        android:pathData="M69,19L69,89"
179
+        android:strokeWidth="0.8"
180
+        android:strokeColor="#33FFFFFF" />
181
+    <path
182
+        android:fillColor="#00000000"
183
+        android:pathData="M79,19L79,89"
184
+        android:strokeWidth="0.8"
185
+        android:strokeColor="#33FFFFFF" />
186
+</vector>
0 187
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+    android:width="@dimen/_108sdp"
3
+    android:height="@dimen/_108sdp"
4
+    android:viewportWidth="108"
5
+    android:viewportHeight="108">
6
+  <path
7
+      android:pathData="M42,70.2C43.65,70.2 45,68.99 45,67.5V40.5C45,39.01 43.65,37.8 42,37.8C40.35,37.8 39,39.01 39,40.5V67.5C39,68.99 40.35,70.2 42,70.2ZM54,81C55.65,81 57,79.79 57,78.3V29.7C57,28.22 55.65,27 54,27C52.35,27 51,28.22 51,29.7V78.3C51,79.79 52.35,81 54,81ZM30,59.4C31.65,59.4 33,58.19 33,56.7V51.3C33,49.81 31.65,48.6 30,48.6C28.35,48.6 27,49.81 27,51.3V56.7C27,58.19 28.35,59.4 30,59.4ZM66,70.2C67.65,70.2 69,68.99 69,67.5V40.5C69,39.01 67.65,37.8 66,37.8C64.35,37.8 63,39.01 63,40.5V67.5C63,68.99 64.35,70.2 66,70.2ZM75,51.3V56.7C75,58.19 76.35,59.4 78,59.4C79.65,59.4 81,58.19 81,56.7V51.3C81,49.81 79.65,48.6 78,48.6C76.35,48.6 75,49.81 75,51.3Z"
8
+      android:fillColor="#986977"/>
9
+</vector>
0 10
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="100dp"
19
+    android:height="100dp"
20
+    android:viewportWidth="100"
21
+    android:viewportHeight="100">
22
+  <path
23
+      android:pathData="M27.778,80C30.833,80 33.333,77.75 33.333,75V25C33.333,22.25 30.833,20 27.778,20C24.722,20 22.222,22.25 22.222,25V75C22.222,77.75 24.722,80 27.778,80ZM50,100C53.056,100 55.556,97.75 55.556,95V5C55.556,2.25 53.056,0 50,0C46.944,0 44.444,2.25 44.444,5V95C44.444,97.75 46.944,100 50,100ZM5.556,60C8.611,60 11.111,57.75 11.111,55V45C11.111,42.25 8.611,40 5.556,40C2.5,40 0,42.25 0,45V55C0,57.75 2.5,60 5.556,60ZM72.222,80C75.278,80 77.778,77.75 77.778,75V25C77.778,22.25 75.278,20 72.222,20C69.167,20 66.667,22.25 66.667,25V75C66.667,77.75 69.167,80 72.222,80ZM88.889,45V55C88.889,57.75 91.389,60 94.444,60C97.5,60 100,57.75 100,55V45C100,42.25 97.5,40 94.444,40C91.389,40 88.889,42.25 88.889,45Z"
24
+      android:fillColor="#986977"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_108sdp"
19
+    android:height="@dimen/_108sdp"
20
+    android:viewportWidth="108"
21
+    android:viewportHeight="108">
22
+  <path
23
+      android:pathData="M42,70.2C43.65,70.2 45,68.99 45,67.5V40.5C45,39.01 43.65,37.8 42,37.8C40.35,37.8 39,39.01 39,40.5V67.5C39,68.99 40.35,70.2 42,70.2ZM54,81C55.65,81 57,79.79 57,78.3V29.7C57,28.22 55.65,27 54,27C52.35,27 51,28.22 51,29.7V78.3C51,79.79 52.35,81 54,81ZM30,59.4C31.65,59.4 33,58.19 33,56.7V51.3C33,49.81 31.65,48.6 30,48.6C28.35,48.6 27,49.81 27,51.3V56.7C27,58.19 28.35,59.4 30,59.4ZM66,70.2C67.65,70.2 69,68.99 69,67.5V40.5C69,39.01 67.65,37.8 66,37.8C64.35,37.8 63,39.01 63,40.5V67.5C63,68.99 64.35,70.2 66,70.2ZM75,51.3V56.7C75,58.19 76.35,59.4 78,59.4C79.65,59.4 81,58.19 81,56.7V51.3C81,49.81 79.65,48.6 78,48.6C76.35,48.6 75,49.81 75,51.3Z"
24
+      android:fillColor="#986977"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"
24
+      android:fillColor="#000000"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,28 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="200dp"
19
+    android:height="200dp"
20
+    android:viewportWidth="200"
21
+    android:viewportHeight="200">
22
+  <path
23
+      android:pathData="M100,100m-100,0a100,100 0,1 1,200 0a100,100 0,1 1,-200 0"
24
+      android:fillColor="#939094"/>
25
+  <path
26
+      android:pathData="M100,110.526C107.114,110.526 112.814,104.884 112.814,97.895L112.857,72.632C112.857,65.642 107.114,60 100,60C92.886,60 87.143,65.642 87.143,72.632V97.895C87.143,104.884 92.886,110.526 100,110.526ZM122.714,97.895C122.714,110.526 111.829,119.368 100,119.368C88.171,119.368 77.286,110.526 77.286,97.895H70C70,112.253 81.657,124.126 95.714,126.189V140H104.286V126.189C118.343,124.168 130,112.295 130,97.895H122.714Z"
27
+      android:fillColor="#313033"/>
28
+</vector>
0 29
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="200dp"
19
+    android:height="200dp"
20
+    android:viewportWidth="200"
21
+    android:viewportHeight="200">
22
+  <path
23
+      android:pathData="M100,100m-98.5,0a98.5,98.5 0,1 1,197 0a98.5,98.5 0,1 1,-197 0"
24
+      android:strokeWidth="3"
25
+      android:fillColor="#00000000"
26
+      android:strokeColor="#EFB8C8"/>
27
+  <path
28
+      android:pathData="M100,100m-85,0a85,85 0,1 1,170 0a85,85 0,1 1,-170 0"
29
+      android:fillColor="#EFB8C8"/>
30
+  <path
31
+      android:pathData="M100,110.526C107.114,110.526 112.814,104.884 112.814,97.895L112.857,72.632C112.857,65.642 107.114,60 100,60C92.886,60 87.143,65.642 87.143,72.632V97.895C87.143,104.884 92.886,110.526 100,110.526ZM122.714,97.895C122.714,110.526 111.829,119.368 100,119.368C88.171,119.368 77.286,110.526 77.286,97.895H70C70,112.253 81.657,124.126 95.714,126.189V140H104.286V126.189C118.343,124.168 130,112.295 130,97.895H122.714Z"
32
+      android:fillColor="#ffffff"/>
33
+</vector>
0 34
new file mode 100644
... ...
@@ -0,0 +1,29 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="18dp"
19
+    android:height="20dp"
20
+    android:viewportWidth="18"
21
+    android:viewportHeight="20">
22
+  <path
23
+      android:pathData="M17,19V17C17,15.9391 16.5786,14.9217 15.8284,14.1716C15.0783,13.4214 14.0609,13 13,13H5C3.9391,13 2.9217,13.4214 2.1716,14.1716C1.4214,14.9217 1,15.9391 1,17V19M13,5C13,7.2091 11.2091,9 9,9C6.7909,9 5,7.2091 5,5C5,2.7909 6.7909,1 9,1C11.2091,1 13,2.7909 13,5Z"
24
+      android:strokeLineJoin="round"
25
+      android:strokeWidth="2"
26
+      android:fillColor="#00000000"
27
+      android:strokeColor="@color/black_day_white_night"
28
+      android:strokeLineCap="round"/>
29
+</vector>
0 30
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M8,6.82v10.36c0,0.79 0.87,1.27 1.54,0.84l8.14,-5.18c0.62,-0.39 0.62,-1.29 0,-1.69L9.54,5.98C8.87,5.55 8,6.03 8,6.82z"
24
+      android:fillColor="#000000"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98 0,-0.34 -0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.09,-0.16 -0.26,-0.25 -0.44,-0.25 -0.06,0 -0.12,0.01 -0.17,0.03l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.06,-0.02 -0.12,-0.03 -0.18,-0.03 -0.17,0 -0.34,0.09 -0.43,0.25l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98 0,0.33 0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.09,0.16 0.26,0.25 0.44,0.25 0.06,0 0.12,-0.01 0.17,-0.03l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.06,0.02 0.12,0.03 0.18,0.03 0.17,0 0.34,-0.09 0.43,-0.25l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM17.45,11.27c0.04,0.31 0.05,0.52 0.05,0.73 0,0.21 -0.02,0.43 -0.05,0.73l-0.14,1.13 0.89,0.7 1.08,0.84 -0.7,1.21 -1.27,-0.51 -1.04,-0.42 -0.9,0.68c-0.43,0.32 -0.84,0.56 -1.25,0.73l-1.06,0.43 -0.16,1.13 -0.2,1.35h-1.4l-0.19,-1.35 -0.16,-1.13 -1.06,-0.43c-0.43,-0.18 -0.83,-0.41 -1.23,-0.71l-0.91,-0.7 -1.06,0.43 -1.27,0.51 -0.7,-1.21 1.08,-0.84 0.89,-0.7 -0.14,-1.13c-0.03,-0.31 -0.05,-0.54 -0.05,-0.74s0.02,-0.43 0.05,-0.73l0.14,-1.13 -0.89,-0.7 -1.08,-0.84 0.7,-1.21 1.27,0.51 1.04,0.42 0.9,-0.68c0.43,-0.32 0.84,-0.56 1.25,-0.73l1.06,-0.43 0.16,-1.13 0.2,-1.35h1.39l0.19,1.35 0.16,1.13 1.06,0.43c0.43,0.18 0.83,0.41 1.23,0.71l0.91,0.7 1.06,-0.43 1.27,-0.51 0.7,1.21 -1.07,0.85 -0.89,0.7 0.14,1.13zM12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"
24
+      android:fillColor="#000000"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="@dimen/_24sdp"
19
+    android:height="@dimen/_24sdp"
20
+    android:viewportWidth="24"
21
+    android:viewportHeight="24">
22
+  <path
23
+      android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92s2.92,-1.31 2.92,-2.92 -1.31,-2.92 -2.92,-2.92z"
24
+      android:fillColor="#000000"/>
25
+</vector>
0 26
new file mode 100644
... ...
@@ -0,0 +1,202 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="862.70325dp"
19
+    android:height="644.78595dp"
20
+    android:viewportWidth="862.70325"
21
+    android:viewportHeight="644.78595">
22
+  <path
23
+      android:pathData="M629.943,612.644l-17.166,0l-8.169,-66.209l25.335,0l0,66.209z"
24
+      android:fillColor="#9e616a"/>
25
+  <path
26
+      android:pathData="M639.003,642.385L626.693,642.385l-2.197,-11.622 -5.628,11.622L586.219,642.385A7.339,7.339 0,0 1,582.049 629.006l26.072,-18.007v-11.75l27.424,1.637Z"
27
+      android:fillColor="#2f2e41"/>
28
+  <path
29
+      android:pathData="M731.923,590.981l-13.775,10.243l-46.063,-48.255l20.33,-15.118l39.508,53.13z"
30
+      android:fillColor="#9e616a"/>
31
+  <path
32
+      android:pathData="M756.94,609.441 L747.062,616.786l-8.698,-8.015 2.419,12.684 -26.199,19.482a7.339,7.339 0,0 1,-11.33 -8.247l10.177,-30.007 -7.011,-9.428 22.983,-15.051Z"
33
+      android:fillColor="#2f2e41"/>
34
+  <path
35
+      android:pathData="M649.927,271.04s32.569,28.138 17.542,108.352l-18.345,78.597 59.829,99.256 -19.077,23.208 -77.78,-107.433 -28.185,-66.114L576.003,289.236Z"
36
+      android:fillColor="#2f2e41"/>
37
+  <path
38
+      android:pathData="M599.447,425.746l-1.959,30.338l5.995,129.281l28.209,-4.913l5.391,-92.046l-37.636,-62.66z"
39
+      android:fillColor="#2f2e41"/>
40
+  <path
41
+      android:pathData="M237.445,628.211l15.351,-0.001l7.302,-59.209l-22.655,0.001l0.002,59.209z"
42
+      android:fillColor="#ffb6b6"/>
43
+  <path
44
+      android:pathData="M233.53,623.199l4.321,-0 16.869,-6.86 9.041,6.859L263.762,623.198A19.266,19.266 0,0 1,283.027 642.463v0.626l-49.497,0.002Z"
45
+      android:fillColor="#2f2e41"/>
46
+  <path
47
+      android:pathData="M296.932,618.538l14.973,3.38l20.166,-56.146l-22.099,-4.99l-13.04,57.756z"
48
+      android:fillColor="#ffb6b6"/>
49
+  <path
50
+      android:pathData="M294.216,612.786l4.215,0.952 17.966,-2.976 7.308,8.682 0.001,0a19.266,19.266 0,0 1,14.549 23.036l-0.138,0.611L289.835,632.19Z"
51
+      android:fillColor="#2f2e41"/>
52
+  <path
53
+      android:pathData="M218.003,266.236c-7.197,21.706 -6.436,45.268 1.73,70.556l3.491,142.378S218.023,572.539 234.806,605.395h24.34l12.051,-134.751 1.513,-90.446 52.182,76.306L291.656,603.192l29.957,2.678 53.934,-159.191L309.003,292.236Z"
54
+      android:fillColor="#2f2e41"/>
55
+  <path
56
+      android:pathData="M498.698,204.408c18.617,-16.777 46.309,-25.212 69.537,-15.805a115.466,115.466 0,0 0,-51.888 59.935c-3.698,9.838 -6.786,21.166 -15.882,26.433 -5.659,3.278 -12.7,3.438 -19.046,1.856 -6.346,-1.582 -12.162,-4.754 -17.899,-7.894l-1.632,-0.037C469.216,244.93 480.08,221.184 498.698,204.408Z"
57
+      android:fillColor="#e6e6e6"/>
58
+  <path
59
+      android:pathData="M568.105,189.112A98.692,98.692 0,0 0,513.199 215.043a42.5,42.5 0,0 0,-8.345 10.377,24.376 24.376,0 0,0 -2.818,12.516c0.101,4.058 0.673,8.198 -0.214,12.21a14.925,14.925 0,0 1,-7.425 9.689c-4.546,2.613 -9.759,3.437 -14.886,4.065 -5.692,0.698 -11.615,1.332 -16.542,4.525 -0.597,0.387 -1.162,-0.562 -0.566,-0.948 8.572,-5.555 19.42,-3.533 28.637,-7.241 4.301,-1.73 8.107,-4.766 9.454,-9.357 1.178,-4.015 0.591,-8.284 0.454,-12.392a26.011,26.011 0,0 1,2.299 -12.34,39.29 39.29,0 0,1 7.916,-10.659 95.749,95.749 0,0 1,24.333 -17.42A100.443,100.443 0,0 1,568.095 188.008c0.703,-0.091 0.709,1.015 0.01,1.105Z"
60
+      android:fillColor="#fff"/>
61
+  <path
62
+      android:pathData="M517.799,210.184a14.807,14.807 0,0 1,1.632 -19.104c0.506,-0.499 1.305,0.265 0.798,0.764a13.711,13.711 0,0 0,-1.482 17.774c0.415,0.577 -0.536,1.14 -0.948,0.566Z"
63
+      android:fillColor="#fff"/>
64
+  <path
65
+      android:pathData="M501.714,235.884a28.539,28.539 0,0 0,20.394 -4.083c0.598,-0.385 1.164,0.564 0.566,0.948a29.685,29.685 0,0 1,-21.23 4.206c-0.701,-0.126 -0.427,-1.197 0.27,-1.071Z"
66
+      android:fillColor="#fff"/>
67
+  <path
68
+      android:pathData="M545.798,194.341a8.381,8.381 0,0 0,6.269 4.894c0.702,0.117 0.427,1.188 -0.27,1.071a9.392,9.392 0,0 1,-6.947 -5.399,0.571 0.571,0 0,1 0.191,-0.757 0.555,0.555 0,0 1,0.757 0.191Z"
69
+      android:fillColor="#fff"/>
70
+  <path
71
+      android:pathData="M593.813,269.508c-0.44,-0.061 -0.881,-0.122 -1.328,-0.176a110.379,110.379 0,0 0,-17.882 -0.908c-0.462,0.007 -0.931,0.021 -1.392,0.041a116.365,116.365 0,0 0,-41.75 9.61,113.005 113.005,0 0,0 -15.163,8.056c-6.688,4.234 -13.602,9.358 -21.078,11.085a19.386,19.386 0,0 1,-2.362 0.421l-30.889,-26.745c-0.04,-0.096 -0.086,-0.185 -0.126,-0.282l-1.282,-1.011c0.239,-0.176 0.49,-0.353 0.729,-0.528 0.138,-0.102 0.283,-0.199 0.421,-0.301 0.094,-0.066 0.189,-0.133 0.27,-0.198 0.031,-0.022 0.063,-0.044 0.088,-0.059 0.081,-0.065 0.164,-0.117 0.239,-0.176q2.103,-1.49 4.235,-2.955c0.006,-0.007 0.006,-0.007 0.019,-0.008a166.157,166.157 0,0 1,34.601 -18.599c0.367,-0.139 0.739,-0.285 1.12,-0.411a107.831,107.831 0,0 1,16.939 -4.767,95.329 95.329,0 0,1 9.553,-1.334 79.272,79.272 0,0 1,24.723 1.752c16.143,3.743 30.91,12.608 39.656,26.433C593.378,268.799 593.596,269.147 593.813,269.508Z"
72
+      android:fillColor="#e6e6e6"/>
73
+  <path
74
+      android:pathData="M593.404,269.839a98.692,98.692 0,0 0,-59.452 -12.353A42.5,42.5 0,0 0,521.042 260.747a24.376,24.376 0,0 0,-9.785 8.297c-2.363,3.301 -4.398,6.951 -7.522,9.62a14.925,14.925 0,0 1,-11.761 3.266c-5.203,-0.651 -9.862,-3.132 -14.333,-5.717 -4.965,-2.87 -10.076,-5.93 -15.932,-6.347 -0.71,-0.051 -0.59,-1.149 0.119,-1.098 10.189,0.726 17.633,8.871 27.225,11.46 4.476,1.208 9.343,1.075 13.182,-1.779 3.358,-2.496 5.459,-6.258 7.823,-9.621a26.011,26.011 0,0 1,9.265 -8.469,39.29 39.29,0 0,1 12.738,-3.745 95.749,95.749 0,0 1,29.917 0.742,100.443 100.443,0 0,1 32.085,11.596c0.616,0.351 -0.045,1.237 -0.657,0.888Z"
75
+      android:fillColor="#fff"/>
76
+  <path
77
+      android:pathData="M540.551,256.376a14.807,14.807 0,0 1,12.805 -14.271c0.705,-0.093 0.883,0.997 0.177,1.09a13.711,13.711 0,0 0,-11.884 13.299c-0.016,0.711 -1.114,0.588 -1.098,-0.119Z"
78
+      android:fillColor="#fff"/>
79
+  <path
80
+      android:pathData="M512.234,267.212a28.539,28.539 0,0 0,18.742 9.018c0.709,0.053 0.59,1.151 -0.119,1.098a29.685,29.685 0,0 1,-19.483 -9.424c-0.484,-0.523 0.38,-1.212 0.861,-0.692Z"
81
+      android:fillColor="#fff"/>
82
+  <path
83
+      android:pathData="M572.445,260.584a8.381,8.381 0,0 0,2.058 7.682c0.49,0.516 -0.374,1.205 -0.861,0.692a9.392,9.392 0,0 1,-2.296 -8.493,0.571 0.571,0 0,1 0.609,-0.49 0.555,0.555 0,0 1,0.49 0.609Z"
84
+      android:fillColor="#fff"/>
85
+  <path
86
+      android:pathData="M51.273,627.136c-1.45,5.44 -5.26,9.97 -9.86,13.27 -0.75,0.54 -1.52,1.04 -2.3,1.51 -0.24,0.14 -0.48,0.29 -0.73,0.42q-0.405,0.24 -0.81,0.45h-21.63c-0.39,-0.79 -0.77,-1.59 -1.15,-2.38 -9.27,-19.48 -15.78,-40.5 -14.67,-61.91a79.254,79.254 0,0 1,5.17 -24.25c5.94,-15.47 16.78,-28.86 31.69,-35.6 0.37,-0.17 0.76,-0.34 1.14,-0.5 -0.12,0.43 -0.24,0.85 -0.36,1.28a110.785,110.785 0,0 0,-3.38 17.59c-0.06,0.46 -0.11,0.92 -0.15,1.39a116.054,116.054 0,0 0,3.72 42.69c0.01,0.03 0.02,0.07 0.03,0.1q1.275,4.605 2.96,9.07c0.88,2.35 1.83,4.67 2.87,6.95C48.153,606.786 53.973,616.986 51.273,627.136Z"
87
+      android:fillColor="#e6e6e6"/>
88
+  <path
89
+      android:pathData="M38.393,518.596c-0.21,0.28 -0.42,0.55 -0.63,0.83a98.129,98.129 0,0 0,-11.12 18.76c-0.16,0.33 -0.31,0.66 -0.44,1a97.813,97.813 0,0 0,-7.82 29.24,1.49 1.49,0 0,0 -0.02,0.21c-0.25,2.36 -0.4,4.74 -0.46,7.12a42.48,42.48 0,0 0,1.43 13.24,23.769 23.769,0 0,0 5.46,9.42c0.25,0.27 0.5,0.54 0.77,0.8 0.2,0.21 0.42,0.42 0.63,0.62 2.02,1.93 4.23,3.72 6.13,5.79a21.432,21.432 0,0 1,2.35 3,14.904 14.904,0 0,1 1.6,12.1c-1.36,5.06 -4.47,9.33 -7.65,13.4 -1.59,2.04 -3.23,4.1 -4.65,6.28 -0.52,0.78 -1,1.57 -1.44,2.38h-1.26c0.42,-0.81 0.88,-1.6 1.38,-2.38 3.65,-5.75 8.84,-10.69 11.53,-17.02 1.82,-4.27 2.37,-9.11 0.07,-13.3a17.682,17.682 0,0 0,-2.43 -3.38c-1.83,-2.07 -4.02,-3.84 -6.01,-5.71 -0.5,-0.47 -0.99,-0.95 -1.46,-1.45a24.964,24.964 0,0 1,-5.64 -8.9,39.23 39.23,0 0,1 -1.94,-13.13c0,-2.84 0.15,-5.7 0.43,-8.54 0.03,-0.36 0.07,-0.73 0.11,-1.1a100.767,100.767 0,0 1,19.67 -49.23c0.2,-0.28 0.41,-0.55 0.62,-0.82C38.033,517.266 38.823,518.046 38.393,518.596Z"
90
+      android:fillColor="#fff"/>
91
+  <path
92
+      android:pathData="M17.717,569.071a14.807,14.807 0,0 1,-12.354 -14.663,0.553 0.553,0 0,1 1.105,-0.024 13.711,13.711 0,0 0,11.52 13.616c0.701,0.114 0.427,1.185 -0.27,1.071Z"
93
+      android:fillColor="#fff"/>
94
+  <path
95
+      android:pathData="M24.516,598.617a28.539,28.539 0,0 0,11.533 -17.308c0.151,-0.695 1.222,-0.424 1.071,0.27a29.685,29.685 0,0 1,-12.038 17.986c-0.585,0.406 -1.148,-0.544 -0.566,-0.948Z"
96
+      android:fillColor="#fff"/>
97
+  <path
98
+      android:pathData="M26.312,538.069a8.381,8.381 0,0 0,7.893 -0.972c0.579,-0.414 1.142,0.538 0.566,0.948a9.392,9.392 0,0 1,-8.73 1.094,0.571 0.571,0 0,1 -0.4,-0.671 0.555,0.555 0,0 1,0.671 -0.4Z"
99
+      android:fillColor="#fff"/>
100
+  <path
101
+      android:pathData="M113.413,557.266c-0.35,0.27 -0.71,0.54 -1.06,0.82a110.362,110.362 0,0 0,-13.29 12c-0.32,0.33 -0.64,0.67 -0.95,1.01l-0.01,0.01a116.347,116.347 0,0 0,-22.66 36.14l-0.03,0.09c-0.01,0.03 -0.02,0.05 -0.03,0.08a114.443,114.443 0,0 0,-5.03 16.42c-1.22,5.46 -2.22,11.31 -4.13,16.57 -0.29,0.81 -0.61,1.61 -0.95,2.38h-44.46c0.15,-0.79 0.31,-1.59 0.47,-2.38a160.302,160.302 0,0 1,10.54 -33.7c0.16,-0.36 0.32,-0.72 0.5,-1.08a108.305,108.305 0,0 1,8.61 -15.35,0.01 0.01,0 0,1 0.01,-0.01 94.956,94.956 0,0 1,5.8 -7.69,79.119 79.119,0 0,1 18.72,-16.24c0.04,-0.03 0.09,-0.05 0.13,-0.08 14.04,-8.71 30.68,-12.86 46.59,-9.27h0.01C112.603,557.076 113.003,557.166 113.413,557.266Z"
102
+      android:fillColor="#e6e6e6"/>
103
+  <path
104
+      android:pathData="M113.363,557.796c-0.34,0.09 -0.68,0.19 -1.01,0.29a98.589,98.589 0,0 0,-20.17 8.27c-0.32,0.17 -0.64,0.35 -0.96,0.53a98.255,98.255 0,0 0,-23.79 18.59,0.035 0.035,0 0,0 -0.01,0.02c-0.08,0.08 -0.17,0.17 -0.24,0.25 -1.6,1.72 -3.14,3.51 -4.6,5.35a42.769,42.769 0,0 0,-6.82 11.43,23.674 23.674,0 0,0 -1.31,10.81c0.03,0.37 0.08,0.73 0.13,1.1 0.04,0.29 0.08,0.58 0.13,0.88 0.66,4.01 1.8,8.03 1.48,12.12a14.909,14.909 0,0 1,-6.01 10.63,23.794 23.794,0 0,1 -3.68,2.34 36.852,36.852 0,0 1,-5.77 2.38h-3.93c0.53,-0.15 1.05,-0.3 1.58,-0.45a48.212,48.212 0,0 0,5.53 -1.93,26.912 26.912,0 0,0 3,-1.48c4.02,-2.31 7.37,-5.85 8.07,-10.58 0.61,-4.14 -0.57,-8.28 -1.27,-12.33 -0.12,-0.7 -0.23,-1.39 -0.29,-2.08a24.439,24.439 0,0 1,0.85 -10.46,39.062 39.062,0 0,1 6.36,-11.66 83.355,83.355 0,0 1,5.48 -6.55q0.36,-0.405 0.75,-0.81a100.901,100.901 0,0 1,24.21 -18.73h0.01a99.288,99.288 0,0 1,21.1 -8.74h0.01c0.33,-0.1 0.67,-0.2 1,-0.29C113.883,556.516 114.043,557.606 113.363,557.796Z"
105
+      android:fillColor="#fff"/>
106
+  <path
107
+      android:pathData="M66.468,585.645a14.807,14.807 0,0 1,-1.036 -19.146c0.432,-0.564 1.329,0.081 0.896,0.646A13.711,13.711 0,0 0,67.328 584.953c0.491,0.514 -0.372,1.203 -0.861,0.692Z"
108
+      android:fillColor="#fff"/>
109
+  <path
110
+      android:pathData="M54.107,613.33a28.539,28.539 0,0 0,19.629 -6.876c0.539,-0.464 1.231,0.397 0.692,0.861a29.685,29.685 0,0 1,-20.441 7.113c-0.712,-0.028 -0.589,-1.126 0.119,-1.098Z"
111
+      android:fillColor="#fff"/>
112
+  <path
113
+      android:pathData="M91.996,566.067a8.381,8.381 0,0 0,6.887 3.977c0.712,0.019 0.588,1.117 -0.119,1.098a9.392,9.392 0,0 1,-7.629 -4.382,0.571 0.571,0 0,1 0.084,-0.776 0.555,0.555 0,0 1,0.776 0.084Z"
114
+      android:fillColor="#fff"/>
115
+  <path
116
+      android:pathData="M456.382,173.13a11.599,11.599 0,0 1,-17.767 0.838l-37.8,16.44 3.682,-21.102 35.331,-12.377a11.662,11.662 0,0 1,16.554 16.201Z"
117
+      android:fillColor="#ffb8b8"/>
118
+  <path
119
+      android:pathData="M431.157,179.718l-87.798,39.108 -0.188,-0.067 -100.067,-35.659a32.96,32.96 0,0 1,-14.782 -42.756h0a32.924,32.924 0,0 1,46.987 -14.637l74.468,44.859 72.211,-9.359Z"
120
+      android:fillColor="#e6e6e6"/>
121
+  <path
122
+      android:pathData="M862.703,643.596a1.186,1.186 0,0 1,-1.19 1.19h-860.29a1.19,1.19 0,0 1,0 -2.38h860.29A1.186,1.186 0,0 1,862.703 643.596Z"
123
+      android:fillColor="#ccc"/>
124
+  <path
125
+      android:pathData="M313.344,296.797l-88.506,-14.157a16.893,16.893 0,0 1,-9.956 -23.646l4.014,-8.028 -1.559,-84.347A62.482,62.482 0,0 1,247.673 111.965l8.631,-5.161 4.362,-11.077 40.22,0.981 0.117,14.527 14.404,22.968 -0,0.095 -0.904,125.014 -3.97,12.901 6.002,15.006Z"
126
+      android:fillColor="#e6e6e6"/>
127
+  <path
128
+      android:pathData="M284.459,45.41m-36.544,0a36.544,36.544 0,1 1,73.088 0a36.544,36.544 0,1 1,-73.088 0"
129
+      android:fillColor="#ffb8b8"/>
130
+  <path
131
+      android:pathData="M246.405,53.376c-1.09,-4.592 -0.59,-11.053 0.026,-15.677 1.615,-12.121 8.346,-23.645 18.573,-30.47a13.38,13.38 0,0 1,6.665 -2.648c2.419,-0.101 5.042,1.194 5.785,3.499a11.993,11.993 0,0 1,6.766 -6.709,21.135 21.135,0 0,1 9.631,-1.297 35.197,35.197 0,0 1,29.363 20.989c0.976,2.319 3.702,-6.246 4.939,-4.055a9.741,9.741 0,0 0,5.524 4.853c2.423,0.676 3.408,10.66 4.361,8.332a11.098,11.098 0,0 1,-10.611 15.475c-2.466,-0.092 -4.825,-0.999 -7.262,-1.39 -8.715,-1.396 -17.96,4.923 -19.823,13.551a23.987,23.987 0,0 0,-3.156 -7.021,8.119 8.119,0 0,0 -6.513,-3.579c-2.48,0.093 -4.659,1.714 -6.268,3.603s-2.817,4.093 -4.438,5.972c-4.755,5.513 -11.187,18.37 -17.965,17.432C256.655,73.496 247.894,59.646 246.405,53.376Z"
132
+      android:fillColor="#2f2e41"/>
133
+  <path
134
+      android:pathData="M505.364,214.541a7.133,7.133 0,0 0,-4.807 -7.854l-98.413,-32.777a7.132,7.132 0,0 0,-2.933 -0.337l-24.667,2.333 -14.154,1.343 -26.119,2.468a7.155,7.155 0,0 0,-6.384 5.99l-13.261,82.838a7.186,7.186 0,0 0,4.484 7.796l99.44,38.384a6.947,6.947 0,0 0,1.446 0.388,7.136 7.136,0 0,0 2.176,0.016l64.255,-9.523a7.121,7.121 0,0 0,6.023 -5.999Z"
135
+      android:fillColor="#fff"/>
136
+  <path
137
+      android:pathData="M321.365,270.503l99.44,38.382a0.897,0.897 0,0 0,0.457 0.054l64.247,-9.522a0.883,0.883 0,0 0,0.755 -0.752l12.92,-85.067a0.905,0.905 0,0 0,-0.599 -0.982l-0.662,-0.224 -97.758,-32.546a0.678,0.678 0,0 0,-0.137 -0.033,0.887 0.887,0 0,0 -0.23,-0.012l-60.164,5.693 -4.774,0.448a0.903,0.903 0,0 0,-0.795 0.748l-13.259,82.834A0.897,0.897 0,0 0,321.365 270.503Z"
138
+      android:fillColor="#986977"/>
139
+  <path
140
+      android:pathData="M339.634,185.495l60.164,-5.693a0.887,0.887 0,0 1,0.23 0.012,0.678 0.678,0 0,1 0.137,0.033l97.758,32.546 -25.787,2.73 -9.65,1.017 -27.46,2.901a1.939,1.939 0,0 1,-0.241 -0.003c-0.049,-0.015 -0.098,-0.029 -0.156,-0.045Z"
141
+      android:fillColor="#2f2e41"/>
142
+  <path
143
+      android:pathData="M319.109,276.345l99.44,38.382a6.722,6.722 0,0 0,1.451 0.38,7.224 7.224,0 0,0 2.177,0.027l64.247,-9.522a7.135,7.135 0,0 0,6.028 -6.004l12.91,-85.068a7.19,7.19 0,0 0,-0.418 -3.717c-0.065,-0.157 -0.131,-0.314 -0.207,-0.462a6.99,6.99 0,0 0,-2.264 -2.698,7.138 7.138,0 0,0 -1.916,-0.977l-0.117,-0.041 -98.292,-32.738a8.955,8.955 0,0 0,-1.227 -0.298,7.086 7.086,0 0,0 -1.715,-0.033l-24.663,2.325 -14.153,1.35L334.269,179.719a7.092,7.092 0,0 0,-3.019 0.997,1.329 1.329,0 0,0 -0.202,0.121 1.192,1.192 0,0 0,-0.13 0.098,7.148 7.148,0 0,0 -3.027,4.764l-13.27,82.843A7.194,7.194 0,0 0,319.109 276.345ZM329.651,185.988a5.3,5.3 0,0 1,1.27 -2.671,4.651 4.651,0 0,1 0.676,-0.659 5.317,5.317 0,0 1,2.324 -1.084,4.059 4.059,0 0,1 0.509,-0.072l43.985,-4.155 20.965,-1.995c0.142,-0.017 0.273,-0.014 0.404,-0.022a5.007,5.007 0,0 1,0.948 0.07,4.145 4.145,0 0,1 0.845,0.201l98.408,32.779c0.078,0.028 0.146,0.054 0.223,0.082a5.218,5.218 0,0 1,2.273 1.654,5.259 5.259,0 0,1 1.121,4.145l-12.921,85.077a5.349,5.349 0,0 1,-4.509 4.502l-64.257,9.521a5.413,5.413 0,0 1,-2.723 -0.31l-99.441,-38.372a5.402,5.402 0,0 1,-3.359 -5.846Z"
144
+      android:fillColor="#3f3d56"/>
145
+  <path
146
+      android:pathData="M330.704,181.387a0.877,0.877 0,0 1,0.268 -0.386,1.051 1.051,0 0,1 0.129,-0.088c0.042,-0.016 0.084,-0.042 0.126,-0.058a0.873,0.873 0,0 1,0.624 -0.011l2.07,0.73 101.116,35.669 23.665,-2.5 13.243,-1.397 28.029,-2.967 2.506,-0.263 0.487,-0.054a0.904,0.904 0,0 1,0.952 0.654,0.739 0.739,0 0,1 0.026,0.143 0.893,0.893 0,0 1,-0.55 0.922,0.988 0.988,0 0,1 -0.248,0.067l-3.409,0.357 -27.603,2.918 -9.65,1.017 -27.46,2.901a1.939,1.939 0,0 1,-0.241 -0.003c-0.049,-0.015 -0.098,-0.029 -0.156,-0.045L331.597,182.658l-0.35,-0.124a0.67,0.67 0,0 1,-0.219 -0.121A0.91,0.91 0,0 1,330.704 181.387Z"
147
+      android:fillColor="#3f3d56"/>
148
+  <path
149
+      android:pathData="M420.271,315.367a0.894,0.894 0,0 1,-0.743 -1.016l14.517,-96.334a0.894,0.894 0,0 1,1.017 -0.751l0.008,0.001a0.894,0.894 0,0 1,0.743 1.016l-14.517,96.334a0.894,0.894 0,0 1,-1.017 0.751Z"
150
+      android:fillColor="#3f3d56"/>
151
+  <path
152
+      android:pathData="M457.068,309.256l-9.655,1.019 11.293,-95.535s12.895,-2.335 13.24,-1.398C472.158,213.901 457.16,308.644 457.068,309.256Z"
153
+      android:fillColor="#3f3d56"/>
154
+  <path
155
+      android:pathData="M331.25,182.533l-0.26,43.567l77.126,29.388l27.697,-37.204l-104.563,-35.751z"
156
+      android:fillColor="#3f3d56"/>
157
+  <path
158
+      android:pathData="M502.483,210.118a5.301,5.301 0,0 0,-2.497 -1.737l-98.406,-32.778a5.106,5.106 0,0 0,-0.848 -0.207,5.009 5.009,0 0,0 -0.951,-0.071l0.16,-0.997 0.985,-0.713 23.368,-16.919 78.041,23.917 0.135,27.052Z"
159
+      android:fillColor="#3f3d56"/>
160
+  <path
161
+      android:pathData="M335.181,252.473a1.513,1.513 0,0 1,0.326 0.068l30.194,9.917a1.5,1.5 0,0 1,-0.936 2.851l-30.194,-9.917a1.5,1.5 0,0 1,0.61 -2.919Z"
162
+      android:fillColor="#fff"/>
163
+  <path
164
+      android:pathData="M457.003,423.236m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"
165
+      android:fillColor="#f2f2f2"/>
166
+  <path
167
+      android:pathData="M151.003,467.236m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"
168
+      android:fillColor="#f2f2f2"/>
169
+  <path
170
+      android:pathData="M401.003,70.236m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"
171
+      android:fillColor="#f2f2f2"/>
172
+  <path
173
+      android:pathData="M420.692,270.121A11.599,11.599 0,0 1,404.785 262.164L363.773,258.021l13.53,-16.606 36.871,6.481a11.662,11.662 0,0 1,6.518 22.226Z"
174
+      android:fillColor="#ffb8b8"/>
175
+  <path
176
+      android:pathData="M395.467,263.534l-95.708,-8.818 -0.131,-0.151L229.776,174.528a32.96,32.96 0,0 1,8.013 -44.523h0a32.924,32.924 0,0 1,48.144 10.209l43.022,75.544 67.565,27.147Z"
177
+      android:fillColor="#e6e6e6"/>
178
+  <path
179
+      android:pathData="M635.69,109.617c-2.377,-17.434 -5.358,-36.152 -17.654,-48.737a41.35,41.35 0,0 0,-59.744 0.618c-8.951,9.549 -12.904,22.957 -13.265,36.04s2.552,26.021 5.784,38.703a119.29,119.29 0,0 0,49.786 -9.799c3.926,-1.704 7.789,-3.631 11.937,-4.686 4.148,-1.056 7.105,1.601 10.963,3.453l2.118,-4.055c1.734,3.227 7.102,2.27 9.05,-0.832C636.612,117.219 636.185,113.246 635.69,109.617Z"
180
+      android:fillColor="#2f2e41"/>
181
+  <path
182
+      android:pathData="M567.884,206.925l-69.876,1.494a11.055,11.055 0,1 0,-4.94 15.574c9.268,0.527 81.772,10.817 86.097,4.185 4.39,-6.731 27.824,-30.486 27.824,-30.486l-18.013,-25.644Z"
183
+      android:fillColor="#9e616a"/>
184
+  <path
185
+      android:pathData="M584.911,94.035m-32.83,0a32.83,32.83 0,1 1,65.66 0a32.83,32.83 0,1 1,-65.66 0"
186
+      android:fillColor="#9e616a"/>
187
+  <path
188
+      android:pathData="M430.713,171.577"
189
+      android:fillColor="#986977"/>
190
+  <path
191
+      android:pathData="M637.494,157.204c-3.869,-7.7 -5.749,-17.212 -13.997,-19.708 -5.57,-1.686 -28.097,0.84 -33.173,3.686 -8.444,4.733 -0.792,13.602 -5.773,21.902 -5.415,9.023 -20.132,27.13 -25.547,36.152 -3.723,6.203 8.817,24.409 6.804,31.358 -2.013,6.948 -2.11,14.747 1.32,21.117 3.069,5.701 -1.371,10.745 1.715,16.437 3.21,5.92 7.148,28.053 4.161,34.088l-2,6c19.847,1.166 36.535,-22.544 56.258,-25.042 4.899,-0.62 9.986,-1.431 14.023,-4.274 5.946,-4.189 8.297,-11.789 9.766,-18.913A159.326,159.326 0,0 0,637.494 157.204Z"
192
+      android:fillColor="#3f3d56"/>
193
+  <path
194
+      android:pathData="M667.25,238.505c-2.764,-7.546 -7.769,-40.537 -7.769,-40.537l-31.324,-0.918 15.314,37.772 -41.79,58.503s0.077,0.129 0.218,0.358a11.052,11.052 0,1 0,9.27 11.745,0.763 0.763,0 0,0 0.958,-0.164C616.776,299.428 670.014,246.051 667.25,238.505Z"
195
+      android:fillColor="#9e616a"/>
196
+  <path
197
+      android:pathData="M670.434,217.67c-2.875,-12.135 -5.772,-24.335 -10.619,-35.826s-11.787,-22.343 -21.547,-30.105c-3.12,-2.482 -6.609,-4.672 -10.521,-5.444 -3.911,-0.772 -8.32,0.092 -11.067,2.981 -4.396,4.624 -3.073,12.045 -1.461,18.218Q622.352,194.795 629.483,222.096q20.594,-2.183 41.188,-4.366Z"
198
+      android:fillColor="#3f3d56"/>
199
+  <path
200
+      android:pathData="M625.139,98.589c-1.209,-7.942 -2.472,-15.95 -5.312,-23.429 -2.84,-7.478 -7.419,-14.482 -13.986,-18.719 -10.399,-6.707 -23.862,-5.414 -35.521,-1.555 -9.016,2.984 -17.818,7.519 -24.176,14.809 -6.358,7.291 -9.93,17.694 -7.564,27.227q18.655,-4.407 37.309,-8.815l-1.361,0.962a30.038,30.038 0,0 1,16.031 20.893,31.122 31.122,0 0,1 -6.566,25.848q12.722,-4.513 25.445,-9.026c5.235,-1.857 10.838,-3.997 13.943,-8.76C626.979,112.5 626.143,105.18 625.139,98.589Z"
201
+      android:fillColor="#2f2e41"/>
202
+</vector>
0 203
new file mode 100644
... ...
@@ -0,0 +1,95 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
18
+    android:width="797.5dp"
19
+    android:height="834.5dp"
20
+    android:viewportWidth="797.5"
21
+    android:viewportHeight="834.5">
22
+  <path
23
+      android:pathData="M0,780a308.5,54.5 0,1 0,617 0a308.5,54.5 0,1 0,-617 0z"
24
+      android:fillColor="#3f3d56"/>
25
+  <path
26
+      android:pathData="M496,301.5m-301.5,0a301.5,301.5 0,1 1,603 0a301.5,301.5 0,1 1,-603 0"
27
+      android:fillColor="#3f3d56"/>
28
+  <path
29
+      android:fillColor="#FF000000"
30
+      android:pathData="M496,301.5m-248.898,0a248.898,248.898 0,1 1,497.796 0a248.898,248.898 0,1 1,-497.796 0"
31
+      android:strokeAlpha="0.05"
32
+      android:fillAlpha="0.05"/>
33
+  <path
34
+      android:fillColor="#FF000000"
35
+      android:pathData="M496,301.5m-203.994,0a203.994,203.994 0,1 1,407.987 0a203.994,203.994 0,1 1,-407.987 0"
36
+      android:strokeAlpha="0.05"
37
+      android:fillAlpha="0.05"/>
38
+  <path
39
+      android:fillColor="#FF000000"
40
+      android:pathData="M496,301.5m-146.26,0a146.26,146.26 0,1 1,292.519 0a146.26,146.26 0,1 1,-292.519 0"
41
+      android:strokeAlpha="0.05"
42
+      android:fillAlpha="0.05"/>
43
+  <path
44
+      android:pathData="M197.17,328.482s-23.704,66.722 -13.169,90.426 27.216,46.53 27.216,46.53S205.072,332.872 197.17,328.482Z"
45
+      android:fillColor="#d0cde1"/>
46
+  <path
47
+      android:fillColor="#FF000000"
48
+      android:pathData="M197.17,328.482s-23.704,66.722 -13.169,90.426 27.216,46.53 27.216,46.53S205.072,332.872 197.17,328.482Z"
49
+      android:strokeAlpha="0.1"
50
+      android:fillAlpha="0.1"/>
51
+  <path
52
+      android:pathData="M213.851,482.997s-1.756,16.681 -2.634,17.558 0.878,2.634 0,5.268 -1.756,6.145 0,7.023 -9.657,78.135 -9.657,78.135 -28.094,36.873 -16.681,94.816l3.512,58.821s27.216,1.756 27.216,-7.901c0,0 -1.756,-11.413 -1.756,-16.681s4.39,-5.268 1.756,-7.901 -2.634,-4.39 -2.634,-4.39 4.39,-3.512 3.512,-4.39 7.901,-63.21 7.901,-63.21 9.657,-9.657 9.657,-14.925v-5.268s4.39,-11.413 4.39,-12.291 23.704,-54.431 23.704,-54.431l9.657,38.629 10.535,55.309s5.268,50.042 15.803,69.356c0,0 18.436,63.211 18.436,61.455s30.727,-6.145 29.849,-14.047 -18.436,-118.52 -18.436,-118.52L332.371,481.241Z"
53
+      android:fillColor="#2f2e41"/>
54
+  <path
55
+      android:pathData="M190.147,740.228s-23.704,46.53 -7.901,48.286 21.948,1.756 28.971,-5.268c3.84,-3.84 11.615,-8.991 17.876,-12.873a23.117,23.117 0,0 0,10.969 -21.982c-0.463,-4.295 -2.068,-7.834 -6.019,-8.164 -10.535,-0.878 -22.826,-10.535 -22.826,-10.535Z"
56
+      android:fillColor="#2f2e41"/>
57
+  <path
58
+      android:pathData="M320.958,774.467s-23.704,46.53 -7.901,48.286 21.948,1.756 28.971,-5.268c3.84,-3.84 11.615,-8.991 17.876,-12.873a23.117,23.117 0,0 0,10.969 -21.982c-0.463,-4.295 -2.068,-7.834 -6.019,-8.164 -10.535,-0.878 -22.826,-10.535 -22.826,-10.535Z"
59
+      android:fillColor="#2f2e41"/>
60
+  <path
61
+      android:pathData="M295.905,215.433m-36.905,0a36.905,36.905 0,1 1,73.809 0a36.905,36.905 0,1 1,-73.809 0"
62
+      android:fillColor="#ffb8b8"/>
63
+  <path
64
+      android:pathData="M272.18,227.558S245.82,276.062 243.711,276.062 291.16,291.878 291.16,291.878s13.707,-46.394 15.816,-50.612Z"
65
+      android:fillColor="#ffb8b8"/>
66
+  <path
67
+      android:pathData="M312.617,280.635s-52.675,-28.971 -57.943,-28.094 -61.455,50.042 -60.577,70.234 7.901,53.553 7.901,53.553 2.634,93.06 7.901,93.938 -0.878,16.681 0.878,16.681 122.909,0 123.787,-2.634S312.617,280.635 312.617,280.635Z"
68
+      android:fillColor="#d0cde1"/>
69
+  <path
70
+      android:pathData="M342.028,489.142s16.681,50.92 2.634,49.164 -20.192,-43.896 -20.192,-43.896Z"
71
+      android:fillColor="#ffb8b8"/>
72
+  <path
73
+      android:pathData="M297.254,277.563s-32.483,7.023 -27.216,50.92 14.925,87.792 14.925,87.792l32.483,71.112 3.512,13.169 23.704,-6.145L327.103,392.571s-6.145,-108.863 -14.047,-112.374A34,34 0,0 0,297.254 277.563Z"
74
+      android:fillColor="#d0cde1"/>
75
+  <path
76
+      android:fillColor="#FF000000"
77
+      android:pathData="M277.5,414.958l40.385,71.989l-34.025,-75.857l-6.36,3.868z"
78
+      android:strokeAlpha="0.1"
79
+      android:fillAlpha="0.1"/>
80
+  <path
81
+      android:pathData="M332.646,204.566l0.122,-2.82 5.61,1.396a6.27,6.27 0,0 0,-2.514 -4.615l5.976,-0.334a64.477,64.477 0,0 0,-43.125 -26.651c-12.926,-1.873 -27.318,0.838 -36.182,10.43 -4.299,4.653 -7.001,10.57 -8.922,16.607 -3.539,11.118 -4.26,24.372 3.12,33.409 7.501,9.185 20.602,10.984 32.406,12.121 4.153,0.4 8.506,0.772 12.355,-0.839a29.721,29.721 0,0 0,-1.654 -13.037,8.687 8.687,0 0,1 -0.879,-4.152c0.525,-3.512 5.209,-4.396 8.728,-3.922s7.75,1.2 10.062,-1.494c1.593,-1.856 1.499,-4.559 1.71,-6.996C320.032,207.035 332.586,205.957 332.646,204.566Z"
82
+      android:fillColor="#2f2e41"/>
83
+  <path
84
+      android:pathData="M559,744.5m-43,0a43,43 0,1 1,86 0a43,43 0,1 1,-86 0"
85
+      android:fillColor="#986977"/>
86
+  <path
87
+      android:pathData="M54,729.5m-43,0a43,43 0,1 1,86 0a43,43 0,1 1,-86 0"
88
+      android:fillColor="#986977"/>
89
+  <path
90
+      android:pathData="M54,672.5m-31,0a31,31 0,1 1,62 0a31,31 0,1 1,-62 0"
91
+      android:fillColor="#986977"/>
92
+  <path
93
+      android:pathData="M54,624.5m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0"
94
+      android:fillColor="#986977"/>
95
+</vector>
0 96
new file mode 100644
1 97
Binary files /dev/null and b/app/src/main/res/drawable/logo.png differ
2 98
new file mode 100644
3 99
Binary files /dev/null and b/app/src/main/res/font/open_sans_bold.ttf differ
4 100
new file mode 100644
5 101
Binary files /dev/null and b/app/src/main/res/font/open_sans_bold_italic.ttf differ
6 102
new file mode 100644
7 103
Binary files /dev/null and b/app/src/main/res/font/open_sans_extra_bold.ttf differ
8 104
new file mode 100644
9 105
Binary files /dev/null and b/app/src/main/res/font/open_sans_extra_bold_italic.ttf differ
10 106
new file mode 100644
11 107
Binary files /dev/null and b/app/src/main/res/font/open_sans_italic.ttf differ
12 108
new file mode 100644
13 109
Binary files /dev/null and b/app/src/main/res/font/open_sans_light.ttf differ
14 110
new file mode 100644
15 111
Binary files /dev/null and b/app/src/main/res/font/open_sans_light_italic.ttf differ
16 112
new file mode 100644
17 113
Binary files /dev/null and b/app/src/main/res/font/open_sans_medium.ttf differ
18 114
new file mode 100644
19 115
Binary files /dev/null and b/app/src/main/res/font/open_sans_medium_italic.ttf differ
20 116
new file mode 100644
21 117
Binary files /dev/null and b/app/src/main/res/font/open_sans_regular.ttf differ
22 118
new file mode 100644
23 119
Binary files /dev/null and b/app/src/main/res/font/open_sans_semi_bold.ttf differ
24 120
new file mode 100644
25 121
Binary files /dev/null and b/app/src/main/res/font/open_sans_semi_bold_italic.ttf differ
26 122
new file mode 100644
... ...
@@ -0,0 +1,27 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
17
+    xmlns:app="http://schemas.android.com/apk/res-auto"
18
+    android:id="@+id/nav_host_fragment"
19
+    android:name="androidx.navigation.fragment.NavHostFragment"
20
+    android:layout_width="match_parent"
21
+    android:layout_height="match_parent"
22
+    app:defaultNavHost="true"
23
+    app:layout_constraintBottom_toBottomOf="parent"
24
+    app:layout_constraintEnd_toEndOf="parent"
25
+    app:layout_constraintStart_toStartOf="parent"
26
+    app:layout_constraintTop_toTopOf="parent"
27
+    app:navGraph="@navigation/navigation" />
0 28
\ No newline at end of file
1 29
new file mode 100644
... ...
@@ -0,0 +1,121 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:tools="http://schemas.android.com/tools"
18
+    xmlns:android="http://schemas.android.com/apk/res/android"
19
+    xmlns:app="http://schemas.android.com/apk/res-auto">
20
+
21
+    <androidx.constraintlayout.widget.ConstraintLayout
22
+        android:id="@+id/bottom_sheet_dialog"
23
+        android:layout_width="match_parent"
24
+        android:layout_height="wrap_content"
25
+        android:background="@color/other_fragment_background"
26
+        android:backgroundTint="#27FFFFFF"
27
+        android:backgroundTintMode="screen"
28
+        app:behavior_hideable="true"
29
+        app:behavior_peekHeight="@dimen/_32sdp"
30
+        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
31
+
32
+        <androidx.appcompat.widget.LinearLayoutCompat
33
+            android:id="@+id/linearLayoutCompat"
34
+            android:layout_width="0dp"
35
+            android:layout_height="wrap_content"
36
+            android:background="@color/other_fragment_background"
37
+            android:orientation="horizontal"
38
+            android:paddingStart="@dimen/_16sdp"
39
+            android:paddingTop="@dimen/_8sdp"
40
+            android:paddingEnd="@dimen/_16sdp"
41
+            android:paddingBottom="@dimen/_8sdp"
42
+            app:layout_constraintEnd_toEndOf="parent"
43
+            app:layout_constraintStart_toStartOf="parent"
44
+            app:layout_constraintTop_toTopOf="parent">
45
+
46
+            <androidx.appcompat.widget.AppCompatImageView
47
+                android:layout_width="wrap_content"
48
+                android:layout_height="wrap_content"
49
+                android:tint="@color/black_day_white_night"
50
+                app:srcCompat="@drawable/ic_mic_black_24dp" />
51
+
52
+            <com.google.android.material.textview.MaterialTextView
53
+                android:layout_width="wrap_content"
54
+                android:layout_height="wrap_content"
55
+                android:layout_marginStart="@dimen/_16sdp"
56
+                android:layout_weight="3"
57
+                android:text="@string/record_player"
58
+                android:textColor="@color/black_day_white_night"
59
+                android:textSize="@dimen/_16ssp"
60
+                android:fontFamily="@font/open_sans_bold"/>
61
+
62
+            <com.google.android.material.textview.MaterialTextView
63
+                android:id="@+id/tv_now_playing"
64
+                android:layout_width="wrap_content"
65
+                android:layout_height="wrap_content"
66
+                android:layout_weight="3"
67
+                android:text="@string/now_playing"
68
+                android:textSize="@dimen/_12ssp"
69
+                android:textColor="@color/black_day_white_night"
70
+                android:fontFamily="@font/open_sans_regular"
71
+                android:textAlignment="textEnd" />
72
+
73
+        </androidx.appcompat.widget.LinearLayoutCompat>
74
+
75
+        <com.google.android.material.textview.MaterialTextView
76
+            android:id="@+id/tv_note_title"
77
+            android:layout_width="0dp"
78
+            android:layout_height="wrap_content"
79
+            android:layout_marginTop="@dimen/_20sdp"
80
+            android:ellipsize="end"
81
+            android:maxLines="1"
82
+            android:textAlignment="center"
83
+            android:textSize="@dimen/_16ssp"
84
+            android:textColor="@color/black_day_white_night"
85
+            android:fontFamily="@font/open_sans_semi_bold"
86
+            app:layout_constraintEnd_toEndOf="parent"
87
+            app:layout_constraintStart_toStartOf="parent"
88
+            app:layout_constraintTop_toBottomOf="@+id/linearLayoutCompat"
89
+            tools:text="CPE 407 - Lecture 1" />
90
+
91
+        <androidx.appcompat.widget.AppCompatImageButton
92
+            android:id="@+id/btn_play"
93
+            android:layout_width="wrap_content"
94
+            android:layout_height="wrap_content"
95
+            android:layout_marginTop="@dimen/_8sdp"
96
+            android:background="@null"
97
+            android:src="@drawable/ic_play_arrow_black_24dp"
98
+            android:tint="@color/black_day_white_night"
99
+            app:layout_constraintEnd_toEndOf="parent"
100
+            app:layout_constraintStart_toStartOf="parent"
101
+            app:layout_constraintTop_toBottomOf="@+id/tv_note_title" />
102
+
103
+        <SeekBar
104
+            android:id="@+id/seekbar"
105
+            style="@android:style/Widget.Material.SeekBar"
106
+            android:layout_width="0dp"
107
+            android:layout_height="wrap_content"
108
+            android:layout_marginStart="@dimen/_16sdp"
109
+            android:layout_marginTop="@dimen/_8sdp"
110
+            android:layout_marginEnd="@dimen/_16sdp"
111
+            android:layout_marginBottom="@dimen/_8sdp"
112
+            android:progress="42"
113
+            android:progressTint="@color/black_day_white_night"
114
+            android:thumbTint="@color/black_day_white_night"
115
+            app:layout_constraintBottom_toBottomOf="parent"
116
+            app:layout_constraintEnd_toEndOf="parent"
117
+            app:layout_constraintStart_toStartOf="parent"
118
+            app:layout_constraintTop_toBottomOf="@+id/btn_play" />
119
+
120
+    </androidx.constraintlayout.widget.ConstraintLayout>
121
+</layout>
0 122
\ No newline at end of file
1 123
new file mode 100644
... ...
@@ -0,0 +1,105 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
17
+    xmlns:app="http://schemas.android.com/apk/res-auto"
18
+    xmlns:tools="http://schemas.android.com/tools">
19
+
20
+    <data>
21
+
22
+        <variable
23
+            name="note"
24
+            type="com.certified.audionote.model.Note" />
25
+
26
+        <import type="com.certified.audionote.utils.UtilKt" />
27
+    </data>
28
+
29
+    <androidx.coordinatorlayout.widget.CoordinatorLayout
30
+        android:layout_width="match_parent"
31
+        android:layout_height="wrap_content">
32
+
33
+        <androidx.constraintlayout.widget.ConstraintLayout
34
+            android:layout_width="match_parent"
35
+            android:layout_height="wrap_content"
36
+            android:padding="@dimen/_8sdp">
37
+
38
+            <androidx.appcompat.widget.AppCompatImageView
39
+                android:id="@+id/appCompatImageView"
40
+                android:layout_width="wrap_content"
41
+                android:layout_height="wrap_content"
42
+                android:layout_margin="@dimen/_8sdp"
43
+                android:contentDescription="@string/alarm_icon"
44
+                android:tint="@color/black_day_white_night"
45
+                app:layout_constraintStart_toStartOf="parent"
46
+                app:layout_constraintTop_toTopOf="parent"
47
+                app:srcCompat="@drawable/ic_alarm_on_black_24dp" />
48
+
49
+            <com.google.android.material.textview.MaterialTextView
50
+                android:id="@+id/tv_reminder_time"
51
+                android:layout_width="wrap_content"
52
+                android:layout_height="wrap_content"
53
+                android:layout_marginStart="@dimen/_16sdp"
54
+                android:fontFamily="@font/open_sans_semi_bold"
55
+                android:text="@{UtilKt.formatTime(note.reminder)}"
56
+                android:textColor="@color/black_day_white_night"
57
+                android:textSize="@dimen/_14ssp"
58
+                app:layout_constraintStart_toEndOf="@id/appCompatImageView"
59
+                app:layout_constraintTop_toTopOf="@id/appCompatImageView"
60
+                tools:text="10:30 AM" />
61
+
62
+            <com.google.android.material.textview.MaterialTextView
63
+                android:id="@+id/tv_reminder_date"
64
+                android:layout_width="wrap_content"
65
+                android:layout_height="wrap_content"
66
+                android:fontFamily="@font/open_sans_regular"
67
+                android:text="@{UtilKt.formatDateOnly(note.reminder)}"
68
+                android:textColor="@color/black_day_white_night"
69
+                android:textSize="@dimen/_12ssp"
70
+                app:layout_constraintStart_toStartOf="@+id/tv_reminder_time"
71
+                app:layout_constraintTop_toBottomOf="@+id/tv_reminder_time"
72
+                tools:text="13th Dec. 2020" />
73
+
74
+            <com.google.android.material.button.MaterialButton
75
+                android:id="@+id/btn_modify_reminder"
76
+                android:layout_width="0dp"
77
+                android:layout_height="wrap_content"
78
+                android:layout_marginStart="@dimen/_8sdp"
79
+                android:layout_marginEnd="@dimen/_8sdp"
80
+                android:backgroundTint="@color/edit_reminder_button_color"
81
+                android:fontFamily="@font/open_sans_semi_bold"
82
+                android:text="@string/modify"
83
+                app:layout_constraintEnd_toEndOf="parent"
84
+                app:layout_constraintStart_toEndOf="@id/btn_delete_reminder"
85
+                app:layout_constraintTop_toTopOf="@id/btn_delete_reminder" />
86
+
87
+            <com.google.android.material.button.MaterialButton
88
+                android:id="@+id/btn_delete_reminder"
89
+                style="?attr/materialButtonOutlinedStyle"
90
+                android:layout_width="0dp"
91
+                android:layout_height="wrap_content"
92
+                android:layout_marginStart="@dimen/_8sdp"
93
+                android:layout_marginTop="@dimen/_16sdp"
94
+                android:layout_marginEnd="@dimen/_8sdp"
95
+                android:fontFamily="@font/open_sans_semi_bold"
96
+                android:text="@string/delete"
97
+                android:textColor="@color/edit_reminder_button_color"
98
+                app:layout_constraintEnd_toStartOf="@id/btn_modify_reminder"
99
+                app:layout_constraintStart_toStartOf="parent"
100
+                app:layout_constraintTop_toBottomOf="@+id/appCompatImageView"
101
+                app:strokeColor="@color/edit_reminder_button_color" />
102
+
103
+        </androidx.constraintlayout.widget.ConstraintLayout>
104
+    </androidx.coordinatorlayout.widget.CoordinatorLayout>
105
+</layout>
0 106
\ No newline at end of file
1 107
new file mode 100644
... ...
@@ -0,0 +1,152 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto"
19
+    xmlns:tools="http://schemas.android.com/tools">
20
+
21
+    <androidx.constraintlayout.widget.ConstraintLayout
22
+        android:layout_width="match_parent"
23
+        android:layout_height="match_parent"
24
+        android:background="@color/fragment_background"
25
+        tools:context=".ui.AboutFragment">
26
+
27
+            <androidx.appcompat.widget.AppCompatImageButton
28
+                android:id="@+id/btn_back"
29
+                app:layout_constraintBottom_toBottomOf="@+id/materialTextView"
30
+                app:layout_constraintStart_toStartOf="parent"
31
+                app:layout_constraintTop_toTopOf="@+id/materialTextView"
32
+                android:background="@null"
33
+                android:padding="@dimen/_4sdp"
34
+                android:layout_marginStart="@dimen/_8sdp"
35
+                android:layout_width="wrap_content"
36
+                android:layout_height="wrap_content"
37
+                android:layout_gravity="center"
38
+                android:tint="@color/black_day_white_night"
39
+                app:srcCompat="@drawable/ic_arrow_back_black_24dp" />
40
+
41
+        <com.google.android.material.textview.MaterialTextView
42
+            android:id="@+id/materialTextView"
43
+            android:layout_width="wrap_content"
44
+            android:layout_height="wrap_content"
45
+            android:layout_marginStart="@dimen/_32sdp"
46
+            android:layout_marginTop="@dimen/_16sdp"
47
+            android:text="@string/about"
48
+            android:fontFamily="@font/open_sans_bold"
49
+            android:textSize="@dimen/_22ssp"
50
+            android:textColor="@color/black_day_white_night"
51
+            app:layout_constraintStart_toEndOf="@+id/btn_back"
52
+            app:layout_constraintTop_toTopOf="parent" />
53
+
54
+        <androidx.constraintlayout.widget.Guideline
55
+            android:id="@+id/guideline3"
56
+            android:layout_width="wrap_content"
57
+            android:layout_height="wrap_content"
58
+            android:orientation="horizontal"
59
+            app:layout_constraintGuide_percent=".2" />
60
+
61
+        <com.google.android.material.card.MaterialCardView
62
+            android:id="@+id/receiver_profile_image"
63
+            android:layout_width="wrap_content"
64
+            android:layout_height="wrap_content"
65
+            android:elevation="@dimen/_4sdp"
66
+            app:cardBackgroundColor="@color/about_icon_color"
67
+            app:cardCornerRadius="@dimen/_16sdp"
68
+            app:cardUseCompatPadding="false"
69
+            app:layout_constraintEnd_toEndOf="parent"
70
+            app:layout_constraintStart_toStartOf="parent"
71
+            app:layout_constraintTop_toTopOf="@+id/guideline3">
72
+
73
+            <androidx.appcompat.widget.AppCompatImageView
74
+                android:layout_width="wrap_content"
75
+                android:layout_height="wrap_content"
76
+                android:layout_margin="@dimen/_8sdp"
77
+                android:src="@drawable/ic_logo_audio_note" />
78
+
79
+        </com.google.android.material.card.MaterialCardView>
80
+
81
+        <com.google.android.material.textview.MaterialTextView
82
+            android:id="@+id/materialTextView4"
83
+            android:layout_width="wrap_content"
84
+            android:layout_height="wrap_content"
85
+            android:text="@string/app_name"
86
+            android:fontFamily="@font/open_sans_bold"
87
+            android:textColor="@color/black_day_white_night"
88
+            android:textSize="@dimen/_14ssp"
89
+            app:layout_constraintEnd_toEndOf="@+id/receiver_profile_image"
90
+            app:layout_constraintStart_toStartOf="@+id/receiver_profile_image"
91
+            app:layout_constraintTop_toBottomOf="@+id/receiver_profile_image" />
92
+
93
+        <com.google.android.material.textview.MaterialTextView
94
+            android:id="@+id/materialTextView5"
95
+            android:layout_width="wrap_content"
96
+            android:layout_height="wrap_content"
97
+            android:text="@string/app_version"
98
+            android:fontFamily="@font/open_sans_regular"
99
+            android:textSize="@dimen/_12ssp"
100
+            app:layout_constraintEnd_toEndOf="parent"
101
+            app:layout_constraintStart_toStartOf="parent"
102
+            app:layout_constraintTop_toBottomOf="@+id/materialTextView4" />
103
+
104
+        <com.google.android.material.card.MaterialCardView
105
+            android:layout_width="0dp"
106
+            android:layout_height="wrap_content"
107
+            android:layout_marginTop="@dimen/_16sdp"
108
+            android:layout_marginStart="@dimen/_16sdp"
109
+            android:layout_marginEnd="@dimen/_16sdp"
110
+            app:cardBackgroundColor="@color/about_icon_color"
111
+            app:cardCornerRadius="@dimen/_10sdp"
112
+            android:elevation="@dimen/_4sdp"
113
+            app:layout_constraintEnd_toEndOf="parent"
114
+            app:layout_constraintStart_toStartOf="parent"
115
+            app:layout_constraintTop_toBottomOf="@+id/materialTextView5">
116
+
117
+            <androidx.constraintlayout.widget.ConstraintLayout
118
+                android:layout_width="match_parent"
119
+                android:layout_height="match_parent">
120
+
121
+                <com.google.android.material.textview.MaterialTextView
122
+                    android:id="@+id/materialTextView7"
123
+                    android:layout_width="wrap_content"
124
+                    android:layout_marginTop="@dimen/_16sdp"
125
+                    android:layout_marginStart="@dimen/_16sdp"
126
+                    android:layout_height="wrap_content"
127
+                    android:text="@string/attributions_amp_licence"
128
+                    android:fontFamily="@font/open_sans_bold"
129
+                    android:textSize="@dimen/_16ssp"
130
+                    android:textColor="@color/black_day_white_night"
131
+                    app:layout_constraintStart_toStartOf="parent"
132
+                    app:layout_constraintTop_toTopOf="parent" />
133
+
134
+                <com.google.android.material.textview.MaterialTextView
135
+                    android:id="@+id/materialTextView6"
136
+                    android:layout_width="0dp"
137
+                    android:layout_height="wrap_content"
138
+                    android:layout_marginBottom="@dimen/_16sdp"
139
+                    android:text="@string/licenced_under_apache_licence_version_2_0"
140
+                    android:textSize="@dimen/_12ssp"
141
+                    android:fontFamily="@font/open_sans_regular"
142
+                    app:layout_constraintBottom_toBottomOf="parent"
143
+                    app:layout_constraintEnd_toEndOf="parent"
144
+                    app:layout_constraintStart_toStartOf="@+id/materialTextView7"
145
+                    app:layout_constraintTop_toBottomOf="@+id/materialTextView7" />
146
+
147
+            </androidx.constraintlayout.widget.ConstraintLayout>
148
+
149
+        </com.google.android.material.card.MaterialCardView>
150
+
151
+    </androidx.constraintlayout.widget.ConstraintLayout>
152
+</layout>
0 153
\ No newline at end of file
1 154
new file mode 100644
... ...
@@ -0,0 +1,256 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto"
19
+    xmlns:tools="http://schemas.android.com/tools"
20
+    tools:context=".ui.AddNoteFragment">
21
+
22
+    <data>
23
+
24
+        <import type="com.certified.audionote.utils.UtilKt" />
25
+
26
+        <import type="com.certified.audionote.utils.ReminderAvailableState" />
27
+
28
+        <import type="com.certified.audionote.utils.ReminderCompletionState" />
29
+
30
+        <variable
31
+            name="viewModel"
32
+            type="com.certified.audionote.ui.NotesViewModel" />
33
+
34
+        <variable
35
+            name="reminderAvailableState"
36
+            type="ReminderAvailableState" />
37
+
38
+        <variable
39
+            name="reminderCompletionState"
40
+            type="ReminderCompletionState" />
41
+
42
+        <variable
43
+            name="note"
44
+            type="com.certified.audionote.model.Note" />
45
+    </data>
46
+
47
+    <androidx.constraintlayout.widget.ConstraintLayout
48
+        android:id="@+id/parent"
49
+        android:layout_width="match_parent"
50
+        android:layout_height="match_parent"
51
+        android:background="@{note.color}">
52
+
53
+        <androidx.appcompat.widget.AppCompatImageButton
54
+            android:id="@+id/btn_back"
55
+            android:layout_width="wrap_content"
56
+            android:layout_height="wrap_content"
57
+            android:layout_gravity="center"
58
+            android:layout_marginStart="@dimen/_8sdp"
59
+            android:layout_marginTop="@dimen/_16sdp"
60
+            android:background="@null"
61
+            android:contentDescription="@string/back_button"
62
+            android:padding="@dimen/_4sdp"
63
+            android:tint="@color/black_day_white_night"
64
+            app:layout_constraintStart_toStartOf="parent"
65
+            app:layout_constraintTop_toTopOf="parent"
66
+            app:srcCompat="@drawable/ic_arrow_back_black_24dp"
67
+            tools:ignore="TouchTargetSizeCheck" />
68
+
69
+        <com.google.android.material.textview.MaterialTextView
70
+            android:id="@+id/tv_title"
71
+            android:layout_width="wrap_content"
72
+            android:layout_height="wrap_content"
73
+            android:layout_marginStart="@dimen/_32sdp"
74
+            android:fontFamily="@font/open_sans_bold"
75
+            android:text="@string/new_note"
76
+            android:textColor="@color/black_day_white_night"
77
+            android:textSize="@dimen/_18ssp"
78
+            app:layout_constraintBottom_toBottomOf="@+id/btn_back"
79
+            app:layout_constraintStart_toEndOf="@+id/btn_back"
80
+            app:layout_constraintTop_toTopOf="@+id/btn_back" />
81
+
82
+        <ScrollView
83
+            android:id="@+id/scrollView2"
84
+            android:layout_width="0dp"
85
+            android:layout_height="0dp"
86
+            android:layout_marginStart="@dimen/_16sdp"
87
+            android:layout_marginEnd="@dimen/_16sdp"
88
+            android:paddingTop="@dimen/_16sdp"
89
+            app:layout_constraintBottom_toTopOf="@+id/card_add_reminder"
90
+            app:layout_constraintEnd_toEndOf="parent"
91
+            app:layout_constraintStart_toStartOf="parent"
92
+            app:layout_constraintTop_toBottomOf="@+id/btn_back">
93
+
94
+            <androidx.constraintlayout.widget.ConstraintLayout
95
+                android:layout_width="match_parent"
96
+                android:layout_height="wrap_content">
97
+
98
+                <com.google.android.material.textfield.TextInputEditText
99
+                    android:id="@+id/et_note_title"
100
+                    android:layout_width="0dp"
101
+                    android:layout_height="wrap_content"
102
+                    android:background="@null"
103
+                    android:fontFamily="@font/open_sans_semi_bold"
104
+                    android:gravity="start|top"
105
+                    android:hint="@string/note_title_required"
106
+                    android:inputType="textMultiLine"
107
+                    android:maxLength="50"
108
+                    android:text="@{note.title}"
109
+                    android:textSize="@dimen/_16ssp"
110
+                    app:layout_constraintEnd_toEndOf="parent"
111
+                    app:layout_constraintStart_toStartOf="parent"
112
+                    app:layout_constraintTop_toTopOf="parent"
113
+                    tools:ignore="TouchTargetSizeCheck,TextContrastCheck" />
114
+
115
+                <com.google.android.material.textfield.TextInputEditText
116
+                    android:id="@+id/et_note_description"
117
+                    android:layout_width="0dp"
118
+                    android:layout_height="0dp"
119
+                    android:layout_marginTop="@dimen/_10sdp"
120
+                    android:background="@null"
121
+                    android:ems="10"
122
+                    android:fontFamily="@font/open_sans_regular"
123
+                    android:gravity="start|top"
124
+                    android:hint="@string/description"
125
+                    android:inputType="textMultiLine"
126
+                    android:text="@{note.description}"
127
+                    android:textSize="@dimen/_12ssp"
128
+                    app:layout_constraintBottom_toTopOf="@+id/guideline2"
129
+                    app:layout_constraintEnd_toEndOf="@+id/et_note_title"
130
+                    app:layout_constraintHorizontal_bias="1.0"
131
+                    app:layout_constraintStart_toStartOf="@+id/et_note_title"
132
+                    app:layout_constraintTop_toBottomOf="@+id/et_note_title"
133
+                    tools:ignore="TextContrastCheck" />
134
+
135
+                <androidx.constraintlayout.widget.Guideline
136
+                    android:id="@+id/guideline2"
137
+                    android:layout_width="wrap_content"
138
+                    android:layout_height="wrap_content"
139
+                    android:orientation="horizontal"
140
+                    app:layout_constraintGuide_percent=".4" />
141
+
142
+                <com.google.android.material.textview.MaterialTextView
143
+                    android:id="@+id/tv_timer"
144
+                    android:layout_width="wrap_content"
145
+                    android:layout_height="wrap_content"
146
+                    android:layout_marginTop="@dimen/_16sdp"
147
+                    android:fontFamily="@font/open_sans_regular"
148
+                    android:textColor="@color/black_day_white_night"
149
+                    android:textSize="@dimen/_24ssp"
150
+                    app:layout_constraintBottom_toTopOf="@+id/btn_record"
151
+                    app:layout_constraintEnd_toEndOf="parent"
152
+                    app:layout_constraintStart_toStartOf="parent"
153
+                    app:layout_constraintTop_toBottomOf="@+id/et_note_description"
154
+                    app:timeText="@{note.audioLength}"
155
+                    tools:text="00:00" />
156
+
157
+                <androidx.appcompat.widget.AppCompatImageButton
158
+                    android:id="@+id/btn_record"
159
+                    android:layout_width="wrap_content"
160
+                    android:layout_height="wrap_content"
161
+                    android:layout_marginTop="@dimen/_16sdp"
162
+                    android:layout_marginBottom="@dimen/_8sdp"
163
+                    android:background="@null"
164
+                    android:contentDescription="@string/record_button"
165
+                    app:layout_constraintBottom_toBottomOf="parent"
166
+                    app:layout_constraintEnd_toEndOf="parent"
167
+                    app:layout_constraintStart_toStartOf="parent"
168
+                    app:layout_constraintTop_toBottomOf="@+id/tv_timer"
169
+                    app:srcCompat="@drawable/ic_mic_not_recording" />
170
+
171
+            </androidx.constraintlayout.widget.ConstraintLayout>
172
+        </ScrollView>
173
+
174
+        <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
175
+            android:id="@+id/fab_save_note"
176
+            android:layout_width="wrap_content"
177
+            android:layout_height="wrap_content"
178
+            android:layout_marginEnd="@dimen/_16sdp"
179
+            android:layout_marginBottom="@dimen/_8sdp"
180
+            android:backgroundTint="@color/fab_background_tint"
181
+            android:text="@string/save"
182
+            android:textAllCaps="false"
183
+            android:textSize="@dimen/_14ssp"
184
+            app:icon="@drawable/ic_done_black_24dp"
185
+            app:iconSize="@dimen/_27sdp"
186
+            app:layout_constraintBottom_toBottomOf="@+id/scrollView2"
187
+            app:layout_constraintEnd_toEndOf="parent" />
188
+
189
+        <com.google.android.material.card.MaterialCardView
190
+            android:id="@+id/card_add_reminder"
191
+            android:layout_width="0dp"
192
+            android:layout_height="wrap_content"
193
+            android:elevation="@dimen/_4sdp"
194
+            app:cardBackgroundColor="@null"
195
+            app:layout_constraintBottom_toBottomOf="parent"
196
+            app:layout_constraintEnd_toEndOf="parent"
197
+            app:layout_constraintStart_toStartOf="parent">
198
+
199
+            <androidx.constraintlayout.widget.ConstraintLayout
200
+                android:id="@+id/parent_add_reminder"
201
+                android:layout_width="match_parent"
202
+                android:layout_height="match_parent"
203
+                android:background="@{note.color}"
204
+                android:backgroundTint="#27FFFFFF"
205
+                android:backgroundTintMode="screen"
206
+                android:paddingStart="@dimen/_8sdp"
207
+                android:paddingTop="@dimen/_4sdp"
208
+                android:paddingEnd="@dimen/_8sdp"
209
+                android:paddingBottom="@dimen/_4sdp">
210
+
211
+                <androidx.appcompat.widget.AppCompatImageButton
212
+                    android:id="@+id/appCompatImageView3"
213
+                    android:layout_width="wrap_content"
214
+                    android:layout_height="wrap_content"
215
+                    android:background="@null"
216
+                    android:padding="@dimen/_4sdp"
217
+                    android:src="@drawable/ic_alarm_on_black_24dp"
218
+                    android:tint="@color/black_day_white_night"
219
+                    app:layout_constraintBottom_toBottomOf="parent"
220
+                    app:layout_constraintStart_toStartOf="parent"
221
+                    app:layout_constraintTop_toTopOf="parent" />
222
+
223
+                <com.google.android.material.textview.MaterialTextView
224
+                    android:id="@+id/tv_reminder_date"
225
+                    android:layout_width="wrap_content"
226
+                    android:layout_height="wrap_content"
227
+                    android:layout_marginStart="@dimen/_16sdp"
228
+                    android:fontFamily="@font/open_sans_regular"
229
+                    android:padding="@dimen/_4sdp"
230
+                    android:text="@{UtilKt.formatReminderDate(note.reminder)}"
231
+                    android:textColor="@color/black_day_white_night"
232
+                    android:textSize="@dimen/_14ssp"
233
+                    app:layout_constraintBottom_toBottomOf="parent"
234
+                    app:layout_constraintStart_toEndOf="@+id/appCompatImageView3"
235
+                    app:layout_constraintTop_toTopOf="parent"
236
+                    app:strikeThrough="@{viewModel.reminderCompletionState == ReminderCompletionState.COMPLETED}"
237
+                    app:visible="@{viewModel.reminderAvailableState == ReminderAvailableState.HAS_REMINDER}" />
238
+
239
+                <com.google.android.material.textview.MaterialTextView
240
+                    android:layout_width="wrap_content"
241
+                    android:layout_height="wrap_content"
242
+                    android:layout_marginStart="@dimen/_16sdp"
243
+                    android:fontFamily="@font/open_sans_regular"
244
+                    android:text="@string/click_to_add_a_reminder_to_this_note"
245
+                    android:textSize="@dimen/_12ssp"
246
+                    app:layout_constraintBottom_toBottomOf="@+id/appCompatImageView3"
247
+                    app:layout_constraintStart_toEndOf="@+id/appCompatImageView3"
248
+                    app:layout_constraintTop_toTopOf="@+id/appCompatImageView3"
249
+                    app:visible="@{viewModel.reminderAvailableState == ReminderAvailableState.NO_REMINDER}" />
250
+
251
+            </androidx.constraintlayout.widget.ConstraintLayout>
252
+
253
+        </com.google.android.material.card.MaterialCardView>
254
+
255
+    </androidx.constraintlayout.widget.ConstraintLayout>
256
+</layout>
0 257
\ No newline at end of file
1 258
new file mode 100644
... ...
@@ -0,0 +1,285 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto"
19
+    xmlns:tools="http://schemas.android.com/tools"
20
+    tools:context=".ui.EditNoteFragment">
21
+
22
+    <data>
23
+
24
+        <import type="com.certified.audionote.utils.UtilKt" />
25
+
26
+        <import type="com.certified.audionote.utils.ReminderAvailableState" />
27
+
28
+        <import type="com.certified.audionote.utils.ReminderCompletionState" />
29
+
30
+        <variable
31
+            name="viewModel"
32
+            type="com.certified.audionote.ui.NotesViewModel" />
33
+
34
+        <variable
35
+            name="reminderAvailableState"
36
+            type="ReminderAvailableState" />
37
+
38
+        <variable
39
+            name="reminderCompletionState"
40
+            type="ReminderCompletionState" />
41
+
42
+        <variable
43
+            name="note"
44
+            type="com.certified.audionote.model.Note" />
45
+    </data>
46
+
47
+    <androidx.constraintlayout.widget.ConstraintLayout
48
+        android:id="@+id/parent"
49
+        android:layout_width="match_parent"
50
+        android:layout_height="match_parent"
51
+        android:background="@{note.color}">
52
+
53
+        <androidx.appcompat.widget.AppCompatImageButton
54
+            android:id="@+id/btn_back"
55
+            android:layout_width="wrap_content"
56
+            android:layout_height="wrap_content"
57
+            android:layout_gravity="center"
58
+            android:layout_marginStart="@dimen/_8sdp"
59
+            android:layout_marginTop="@dimen/_16sdp"
60
+            android:background="@null"
61
+            android:contentDescription="@string/back_button"
62
+            android:padding="@dimen/_4sdp"
63
+            android:tint="@color/black_day_white_night"
64
+            app:layout_constraintStart_toStartOf="parent"
65
+            app:layout_constraintTop_toTopOf="parent"
66
+            app:srcCompat="@drawable/ic_arrow_back_black_24dp"
67
+            tools:ignore="TouchTargetSizeCheck" />
68
+
69
+        <androidx.appcompat.widget.AppCompatImageButton
70
+            android:id="@+id/btn_share"
71
+            android:layout_width="wrap_content"
72
+            android:layout_height="wrap_content"
73
+            android:layout_gravity="center"
74
+            android:layout_marginEnd="@dimen/_8sdp"
75
+            android:background="@null"
76
+            android:contentDescription="@string/share_button"
77
+            android:padding="@dimen/_4sdp"
78
+            android:tint="@color/black_day_white_night"
79
+            app:layout_constraintEnd_toEndOf="parent"
80
+            app:layout_constraintTop_toTopOf="@+id/btn_delete"
81
+            app:srcCompat="@drawable/ic_share_black_24dp"
82
+            tools:ignore="TouchTargetSizeCheck" />
83
+
84
+        <androidx.appcompat.widget.AppCompatImageButton
85
+            android:id="@+id/btn_delete"
86
+            android:layout_width="wrap_content"
87
+            android:layout_height="wrap_content"
88
+            android:layout_marginEnd="@dimen/_8sdp"
89
+            android:background="@null"
90
+            android:contentDescription="@string/delete_button"
91
+            android:padding="@dimen/_4sdp"
92
+            android:tint="@color/black_day_white_night"
93
+            app:layout_constraintEnd_toStartOf="@+id/btn_share"
94
+            app:layout_constraintTop_toTopOf="@+id/btn_back"
95
+            app:srcCompat="@drawable/ic_delete_black_24dp"
96
+            tools:ignore="TouchTargetSizeCheck" />
97
+
98
+        <com.google.android.material.textview.MaterialTextView
99
+            android:id="@+id/tv_title"
100
+            android:layout_width="wrap_content"
101
+            android:layout_height="wrap_content"
102
+            android:layout_marginStart="@dimen/_32sdp"
103
+            android:fontFamily="@font/open_sans_bold"
104
+            android:text="@string/edit_note"
105
+            android:textColor="@color/black_day_white_night"
106
+            android:textSize="@dimen/_18ssp"
107
+            app:layout_constraintBottom_toBottomOf="@+id/btn_back"
108
+            app:layout_constraintStart_toEndOf="@+id/btn_back"
109
+            app:layout_constraintTop_toTopOf="@+id/btn_back" />
110
+
111
+        <ScrollView
112
+            android:id="@+id/scrollView2"
113
+            android:layout_width="0dp"
114
+            android:layout_height="0dp"
115
+            android:layout_marginStart="@dimen/_16sdp"
116
+            android:layout_marginEnd="@dimen/_16sdp"
117
+            android:paddingTop="@dimen/_16sdp"
118
+            app:layout_constraintBottom_toTopOf="@+id/card_add_reminder"
119
+            app:layout_constraintEnd_toEndOf="parent"
120
+            app:layout_constraintStart_toStartOf="parent"
121
+            app:layout_constraintTop_toBottomOf="@+id/btn_back">
122
+
123
+            <androidx.constraintlayout.widget.ConstraintLayout
124
+                android:layout_width="match_parent"
125
+                android:layout_height="wrap_content">
126
+
127
+                <com.google.android.material.textfield.TextInputEditText
128
+                    android:id="@+id/et_note_title"
129
+                    android:layout_width="0dp"
130
+                    android:layout_height="wrap_content"
131
+                    android:background="@null"
132
+                    android:fontFamily="@font/open_sans_semi_bold"
133
+                    android:gravity="start|top"
134
+                    android:hint="@string/note_title_required"
135
+                    android:inputType="textMultiLine"
136
+                    android:maxLength="50"
137
+                    android:text="@{note.title}"
138
+                    android:textSize="@dimen/_16ssp"
139
+                    app:layout_constraintEnd_toEndOf="parent"
140
+                    app:layout_constraintStart_toStartOf="parent"
141
+                    app:layout_constraintTop_toTopOf="parent"
142
+                    tools:ignore="TouchTargetSizeCheck,TextContrastCheck" />
143
+
144
+                <com.google.android.material.textfield.TextInputEditText
145
+                    android:id="@+id/et_note_description"
146
+                    android:layout_width="0dp"
147
+                    android:layout_height="0dp"
148
+                    android:layout_marginTop="@dimen/_10sdp"
149
+                    android:background="@null"
150
+                    android:ems="10"
151
+                    android:fontFamily="@font/open_sans_regular"
152
+                    android:gravity="start|top"
153
+                    android:hint="@string/description"
154
+                    android:inputType="textMultiLine"
155
+                    android:text="@{note.description}"
156
+                    android:textSize="@dimen/_12ssp"
157
+                    app:layout_constraintBottom_toTopOf="@+id/guideline2"
158
+                    app:layout_constraintEnd_toEndOf="@+id/et_note_title"
159
+                    app:layout_constraintHorizontal_bias="1.0"
160
+                    app:layout_constraintStart_toStartOf="@+id/et_note_title"
161
+                    app:layout_constraintTop_toBottomOf="@+id/et_note_title"
162
+                    tools:ignore="TextContrastCheck" />
163
+
164
+                <androidx.constraintlayout.widget.Guideline
165
+                    android:id="@+id/guideline2"
166
+                    android:layout_width="wrap_content"
167
+                    android:layout_height="wrap_content"
168
+                    android:orientation="horizontal"
169
+                    app:layout_constraintGuide_percent=".4" />
170
+
171
+                <com.google.android.material.textview.MaterialTextView
172
+                    android:id="@+id/tv_timer"
173
+                    android:layout_width="wrap_content"
174
+                    android:layout_height="wrap_content"
175
+                    android:layout_marginTop="@dimen/_16sdp"
176
+                    android:fontFamily="@font/open_sans_regular"
177
+                    android:textColor="@color/black_day_white_night"
178
+                    android:textSize="@dimen/_24ssp"
179
+                    app:layout_constraintBottom_toTopOf="@+id/btn_record"
180
+                    app:layout_constraintEnd_toEndOf="parent"
181
+                    app:layout_constraintStart_toStartOf="parent"
182
+                    app:layout_constraintTop_toBottomOf="@+id/et_note_description"
183
+                    app:timeText="@{note.audioLength}"
184
+                    tools:text="00:00" />
185
+
186
+                <androidx.appcompat.widget.AppCompatImageButton
187
+                    android:id="@+id/btn_record"
188
+                    android:layout_width="wrap_content"
189
+                    android:layout_height="wrap_content"
190
+                    android:layout_marginTop="@dimen/_16sdp"
191
+                    android:layout_marginBottom="@dimen/_8sdp"
192
+                    android:background="@null"
193
+                    android:contentDescription="@string/record_button"
194
+                    app:layout_constraintBottom_toBottomOf="parent"
195
+                    app:layout_constraintEnd_toEndOf="parent"
196
+                    app:layout_constraintStart_toStartOf="parent"
197
+                    app:layout_constraintTop_toBottomOf="@+id/tv_timer"
198
+                    app:srcCompat="@drawable/ic_audio_not_playing" />
199
+
200
+            </androidx.constraintlayout.widget.ConstraintLayout>
201
+        </ScrollView>
202
+
203
+        <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
204
+            android:id="@+id/fab_update_note"
205
+            android:layout_width="wrap_content"
206
+            android:layout_height="wrap_content"
207
+            android:layout_marginEnd="@dimen/_16sdp"
208
+            android:layout_marginBottom="@dimen/_8sdp"
209
+            android:backgroundTint="@color/fab_background_tint"
210
+            android:text="@string/save"
211
+            android:textAllCaps="false"
212
+            android:textSize="@dimen/_14ssp"
213
+            app:icon="@drawable/ic_done_black_24dp"
214
+            app:iconSize="@dimen/_27sdp"
215
+            app:layout_constraintBottom_toBottomOf="@+id/scrollView2"
216
+            app:layout_constraintEnd_toEndOf="parent" />
217
+
218
+        <com.google.android.material.card.MaterialCardView
219
+            android:id="@+id/card_add_reminder"
220
+            android:layout_width="0dp"
221
+            android:layout_height="wrap_content"
222
+            android:elevation="@dimen/_4sdp"
223
+            app:cardBackgroundColor="@null"
224
+            app:layout_constraintBottom_toBottomOf="parent"
225
+            app:layout_constraintEnd_toEndOf="parent"
226
+            app:layout_constraintStart_toStartOf="parent">
227
+
228
+            <androidx.constraintlayout.widget.ConstraintLayout
229
+                android:id="@+id/parent_add_reminder"
230
+                android:layout_width="match_parent"
231
+                android:layout_height="match_parent"
232
+                android:background="@{note.color}"
233
+                android:backgroundTint="#27FFFFFF"
234
+                android:backgroundTintMode="screen"
235
+                android:paddingStart="@dimen/_8sdp"
236
+                android:paddingTop="@dimen/_4sdp"
237
+                android:paddingEnd="@dimen/_8sdp"
238
+                android:paddingBottom="@dimen/_4sdp">
239
+
240
+                <androidx.appcompat.widget.AppCompatImageButton
241
+                    android:id="@+id/appCompatImageView3"
242
+                    android:layout_width="wrap_content"
243
+                    android:layout_height="wrap_content"
244
+                    android:background="@null"
245
+                    android:padding="@dimen/_4sdp"
246
+                    android:src="@drawable/ic_alarm_on_black_24dp"
247
+                    android:tint="@color/black_day_white_night"
248
+                    app:layout_constraintBottom_toBottomOf="parent"
249
+                    app:layout_constraintStart_toStartOf="parent"
250
+                    app:layout_constraintTop_toTopOf="parent" />
251
+
252
+                <com.google.android.material.textview.MaterialTextView
253
+                    android:id="@+id/tv_reminder_date"
254
+                    android:layout_width="wrap_content"
255
+                    android:layout_height="wrap_content"
256
+                    android:layout_marginStart="@dimen/_16sdp"
257
+                    android:fontFamily="@font/open_sans_regular"
258
+                    android:padding="@dimen/_4sdp"
259
+                    android:text="@{UtilKt.formatReminderDate(note.reminder)}"
260
+                    android:textColor="@color/black_day_white_night"
261
+                    android:textSize="@dimen/_14ssp"
262
+                    app:layout_constraintBottom_toBottomOf="parent"
263
+                    app:layout_constraintStart_toEndOf="@+id/appCompatImageView3"
264
+                    app:layout_constraintTop_toTopOf="parent"
265
+                    app:strikeThrough="@{viewModel.reminderCompletionState == ReminderCompletionState.COMPLETED}"
266
+                    app:visible="@{viewModel.reminderAvailableState == ReminderAvailableState.HAS_REMINDER}" />
267
+
268
+                <com.google.android.material.textview.MaterialTextView
269
+                    android:layout_width="wrap_content"
270
+                    android:layout_height="wrap_content"
271
+                    android:layout_marginStart="@dimen/_16sdp"
272
+                    android:fontFamily="@font/open_sans_regular"
273
+                    android:text="@string/click_to_add_a_reminder_to_this_note"
274
+                    android:textSize="@dimen/_12ssp"
275
+                    app:layout_constraintBottom_toBottomOf="@+id/appCompatImageView3"
276
+                    app:layout_constraintStart_toEndOf="@+id/appCompatImageView3"
277
+                    app:layout_constraintTop_toTopOf="@+id/appCompatImageView3"
278
+                    app:visible="@{viewModel.reminderAvailableState == ReminderAvailableState.NO_REMINDER}" />
279
+
280
+            </androidx.constraintlayout.widget.ConstraintLayout>
281
+
282
+        </com.google.android.material.card.MaterialCardView>
283
+
284
+    </androidx.constraintlayout.widget.ConstraintLayout>
285
+</layout>
0 286
\ No newline at end of file
1 287
new file mode 100644
... ...
@@ -0,0 +1,192 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto"
19
+    xmlns:tools="http://schemas.android.com/tools">
20
+
21
+    <data>
22
+
23
+        <import type="androidx.databinding.ObservableField" />
24
+
25
+        <import type="com.certified.audionote.utils.UIState" />
26
+
27
+        <variable
28
+            name="uiState"
29
+            type="UIState" />
30
+
31
+        <variable
32
+            name="viewModel"
33
+            type="com.certified.audionote.ui.NotesViewModel" />
34
+    </data>
35
+
36
+    <androidx.coordinatorlayout.widget.CoordinatorLayout
37
+        android:layout_width="match_parent"
38
+        android:background="@color/fragment_background"
39
+        android:layout_height="match_parent">
40
+
41
+        <androidx.constraintlayout.widget.ConstraintLayout
42
+            android:layout_width="match_parent"
43
+            android:layout_height="match_parent"
44
+            tools:context=".ui.HomeFragment">
45
+
46
+                <androidx.appcompat.widget.AppCompatImageButton
47
+                    android:id="@+id/btn_settings"
48
+                    android:background="@null"
49
+                    android:padding="@dimen/_4sdp"
50
+                    android:layout_width="wrap_content"
51
+                    android:layout_height="wrap_content"
52
+                    android:layout_gravity="center"
53
+                    android:tint="@color/black_day_white_night"
54
+                    app:srcCompat="@drawable/ic_settings_black_24dp"
55
+                    app:layout_constraintBottom_toBottomOf="@+id/materialTextView3"
56
+                    app:layout_constraintEnd_toEndOf="@+id/fab_add_note"
57
+                    app:layout_constraintTop_toTopOf="@+id/materialTextView2" />
58
+
59
+            <com.google.android.material.textview.MaterialTextView
60
+                android:id="@+id/materialTextView2"
61
+                android:layout_width="wrap_content"
62
+                android:layout_height="wrap_content"
63
+                android:layout_marginStart="@dimen/_16sdp"
64
+                android:layout_marginTop="@dimen/_16sdp"
65
+                android:text="@string/hi_there"
66
+                android:textSize="@dimen/_18ssp"
67
+                android:textColor="@color/black_day_white_night"
68
+                android:fontFamily="@font/open_sans_bold"
69
+                app:layout_constraintStart_toStartOf="parent"
70
+                app:layout_constraintTop_toTopOf="parent" />
71
+
72
+            <com.google.android.material.textview.MaterialTextView
73
+                android:id="@+id/materialTextView3"
74
+                android:layout_width="wrap_content"
75
+                android:layout_height="wrap_content"
76
+                android:alpha=".7"
77
+                android:text="@string/welcome_back"
78
+                android:fontFamily="@font/open_sans_medium"
79
+                android:textSize="@dimen/_12ssp"
80
+                app:layout_constraintStart_toStartOf="@+id/materialTextView2"
81
+                app:layout_constraintTop_toBottomOf="@+id/materialTextView2" />
82
+
83
+            <androidx.recyclerview.widget.RecyclerView
84
+                android:id="@+id/recycler_view_notes"
85
+                android:layout_width="0dp"
86
+                android:layout_height="0dp"
87
+                android:layout_marginTop="@dimen/_16sdp"
88
+                android:layout_marginStart="@dimen/_8sdp"
89
+                android:layout_marginEnd="@dimen/_8sdp"
90
+                app:layout_constraintBottom_toBottomOf="parent"
91
+                app:layout_constraintEnd_toEndOf="parent"
92
+                app:layout_constraintStart_toStartOf="parent"
93
+                app:layout_constraintTop_toBottomOf="@+id/materialTextView3"
94
+                app:listItems="@{viewModel.notes}"
95
+                app:visible="@{viewModel.uiState == UIState.HAS_DATA}"
96
+                tools:listitem="@layout/item_note" />
97
+
98
+<!--            <com.google.android.material.textview.MaterialTextView-->
99
+<!--                android:id="@+id/materialTextView"-->
100
+<!--                android:layout_width="0dp"-->
101
+<!--                android:textColor="@color/titleText"-->
102
+<!--                android:layout_marginEnd="@dimen/_16sdp"-->
103
+<!--                android:layout_marginStart="@dimen/_16sdp"-->
104
+<!--                android:layout_height="wrap_content"-->
105
+<!--                android:text="“The more that you read, the more things you will know, the more that you learn, the more places you’ll go.”"-->
106
+<!--                android:textAlignment="center"-->
107
+<!--                android:alpha=".7"-->
108
+<!--                android:textSize="@dimen/_14ssp"-->
109
+<!--                android:fontFamily="@font/open_sans_medium_italic"-->
110
+<!--                app:layout_constraintBottom_toTopOf="@+id/materialTextView4"-->
111
+<!--                app:layout_constraintEnd_toEndOf="parent"-->
112
+<!--                app:layout_constraintHorizontal_bias="0.5"-->
113
+<!--                app:layout_constraintStart_toStartOf="parent"-->
114
+<!--                app:layout_constraintTop_toTopOf="parent"-->
115
+<!--                app:layout_constraintVertical_chainStyle="packed" />-->
116
+
117
+<!--            <com.google.android.material.textview.MaterialTextView-->
118
+<!--                android:id="@+id/materialTextView4"-->
119
+<!--                android:layout_width="wrap_content"-->
120
+<!--                android:layout_height="wrap_content"-->
121
+<!--                android:text="– Dr. Seuss"-->
122
+<!--                android:scrollbarSize="@dimen/_18ssp"-->
123
+<!--                android:textColor="@color/titleText"-->
124
+<!--                android:fontFamily="@font/open_sans_bold_italic"-->
125
+<!--                android:textSize="@dimen/_18ssp"-->
126
+<!--                app:layout_constraintBottom_toBottomOf="parent"-->
127
+<!--                app:layout_constraintEnd_toEndOf="@+id/materialTextView"-->
128
+<!--                app:layout_constraintHorizontal_bias="0.5"-->
129
+<!--                app:layout_constraintStart_toStartOf="@+id/materialTextView"-->
130
+<!--                app:layout_constraintTop_toBottomOf="@+id/materialTextView" />-->
131
+
132
+            <androidx.appcompat.widget.AppCompatImageView
133
+                android:id="@+id/iv_empty_notes"
134
+                android:layout_width="0dp"
135
+                android:layout_height="0dp"
136
+                android:layout_margin="@dimen/_16sdp"
137
+                android:src="@drawable/ic_undraw_empty"
138
+                app:layout_constraintBottom_toTopOf="@+id/fab_add_note"
139
+                app:layout_constraintEnd_toEndOf="@+id/fab_add_note"
140
+                app:layout_constraintHorizontal_bias="1.0"
141
+                app:layout_constraintStart_toStartOf="@+id/materialTextView3"
142
+                app:layout_constraintTop_toBottomOf="@+id/materialTextView3"
143
+                app:layout_constraintVertical_bias="1.0" />
144
+
145
+            <com.google.android.material.textview.MaterialTextView
146
+                android:id="@+id/tv_empty_notes"
147
+                android:layout_width="wrap_content"
148
+                android:layout_height="wrap_content"
149
+                android:layout_marginBottom="@dimen/_8sdp"
150
+                android:alpha=".7"
151
+                app:fontFamily="@font/open_sans_semi_bold"
152
+                android:textColor="@color/titleText"
153
+                android:paddingStart="@dimen/_16sdp"
154
+                android:paddingEnd="@dimen/_16sdp"
155
+                android:text="@string/your_record_list_is_empty_click_the_button_below_to_get_started"
156
+                android:textAlignment="center"
157
+                android:textSize="@dimen/_12ssp"
158
+                android:fontFamily="@font/open_sans_regular"
159
+                app:layout_constraintBottom_toBottomOf="@+id/iv_empty_notes"
160
+                app:layout_constraintEnd_toEndOf="@+id/iv_empty_notes"
161
+                app:layout_constraintStart_toStartOf="@+id/iv_empty_notes" />
162
+
163
+            <androidx.constraintlayout.widget.Group
164
+                android:id="@+id/group_empty_notes"
165
+                android:layout_width="wrap_content"
166
+                android:layout_height="wrap_content"
167
+                android:visibility="visible"
168
+                app:constraint_referenced_ids="iv_empty_notes, tv_empty_notes"
169
+                app:visible="@{viewModel.uiState == UIState.EMPTY}" />
170
+
171
+            <com.google.android.material.floatingactionbutton.FloatingActionButton
172
+                android:id="@+id/fab_add_note"
173
+                android:layout_width="wrap_content"
174
+                android:layout_height="wrap_content"
175
+                android:layout_marginEnd="@dimen/_16sdp"
176
+                android:layout_marginBottom="@dimen/_16sdp"
177
+                android:backgroundTint="@color/fab_background_tint"
178
+                android:contentDescription="@string/add_note_button"
179
+                app:iconSize="@dimen/_27sdp"
180
+                app:layout_constraintBottom_toBottomOf="parent"
181
+                app:layout_constraintEnd_toEndOf="parent"
182
+                app:srcCompat="@drawable/ic_mic_black_24dp" />
183
+
184
+        </androidx.constraintlayout.widget.ConstraintLayout>
185
+
186
+        <include
187
+            android:visibility="gone"
188
+            android:id="@+id/bottom_sheet_dialog_layout"
189
+            layout="@layout/bottom_sheet_dialog" />
190
+
191
+    </androidx.coordinatorlayout.widget.CoordinatorLayout>
192
+</layout>
0 193
\ No newline at end of file
1 194
new file mode 100644
... ...
@@ -0,0 +1,86 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
19
+    xmlns:app="http://schemas.android.com/apk/res-auto"
20
+    xmlns:tools="http://schemas.android.com/tools"
21
+    android:layout_width="match_parent"
22
+    android:layout_height="match_parent"
23
+    android:background="@color/fragment_background"
24
+    tools:context=".ui.OnboardingFragment">
25
+
26
+    <androidx.viewpager2.widget.ViewPager2
27
+        android:id="@+id/view_pager"
28
+        android:layout_width="0dp"
29
+        android:layout_height="0dp"
30
+        android:layout_marginTop="16dp"
31
+        android:layout_marginBottom="16dp"
32
+        app:layout_constraintBottom_toTopOf="@+id/btn_get_started"
33
+        app:layout_constraintEnd_toEndOf="parent"
34
+        app:layout_constraintHorizontal_bias="0.0"
35
+        app:layout_constraintStart_toStartOf="parent"
36
+        app:layout_constraintTop_toTopOf="parent"
37
+        app:layout_constraintVertical_bias="0.0" />
38
+
39
+    <com.google.android.material.button.MaterialButton
40
+        android:id="@+id/btn_get_started"
41
+        android:layout_width="0dp"
42
+        android:layout_height="wrap_content"
43
+        android:layout_marginBottom="@dimen/_16sdp"
44
+        android:backgroundTint="@color/primary_dark"
45
+        android:fontFamily="@font/open_sans_semi_bold"
46
+        android:text="@string/get_started"
47
+        android:textSize="@dimen/_14ssp"
48
+        android:textAllCaps="false"
49
+        android:textColor="@color/black_day_white_night"
50
+        app:layout_constraintBottom_toTopOf="@+id/indicator"
51
+        app:layout_constraintEnd_toStartOf="@+id/guideline5"
52
+        app:layout_constraintStart_toStartOf="@+id/guideline4" />
53
+
54
+    <com.rd.PageIndicatorView
55
+        android:id="@+id/indicator"
56
+        android:layout_width="wrap_content"
57
+        android:layout_height="wrap_content"
58
+        android:layout_marginBottom="@dimen/_64sdp"
59
+        android:background="@android:color/transparent"
60
+        app:layout_constraintBottom_toBottomOf="parent"
61
+        app:layout_constraintEnd_toEndOf="@+id/btn_get_started"
62
+        app:layout_constraintStart_toStartOf="@+id/btn_get_started"
63
+        app:piv_animationType="worm"
64
+        app:piv_count="3"
65
+        app:piv_dynamicCount="true"
66
+        app:piv_interactiveAnimation="true"
67
+        app:piv_padding="6dp"
68
+        app:piv_selectedColor="@color/primary_dark"
69
+        app:piv_unselectedColor="@color/grey"
70
+        app:piv_viewPager="@id/view_pager" />
71
+
72
+    <androidx.constraintlayout.widget.Guideline
73
+        android:id="@+id/guideline4"
74
+        android:layout_width="wrap_content"
75
+        android:layout_height="wrap_content"
76
+        android:orientation="vertical"
77
+        app:layout_constraintGuide_percent=".3"/>
78
+
79
+    <androidx.constraintlayout.widget.Guideline
80
+        android:id="@+id/guideline5"
81
+        android:layout_width="wrap_content"
82
+        android:layout_height="wrap_content"
83
+        android:orientation="vertical"
84
+        app:layout_constraintGuide_percent=".7"/>
85
+
86
+</androidx.constraintlayout.widget.ConstraintLayout>
0 87
\ No newline at end of file
1 88
new file mode 100644
... ...
@@ -0,0 +1,126 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto">
19
+
20
+    <androidx.constraintlayout.widget.ConstraintLayout
21
+        android:layout_width="match_parent"
22
+        android:layout_height="match_parent"
23
+        android:background="@color/fragment_background">
24
+
25
+        <androidx.appcompat.widget.AppCompatImageButton
26
+            android:id="@+id/btn_back"
27
+            android:layout_width="wrap_content"
28
+            android:layout_height="wrap_content"
29
+            android:layout_gravity="center"
30
+            android:background="@null"
31
+            android:padding="@dimen/_4sdp"
32
+            android:tint="@color/black_day_white_night"
33
+            android:layout_marginStart="@dimen/_8sdp"
34
+            app:layout_constraintBottom_toBottomOf="@+id/materialTextView"
35
+            app:layout_constraintStart_toStartOf="parent"
36
+            app:layout_constraintTop_toTopOf="@+id/materialTextView"
37
+            app:srcCompat="@drawable/ic_arrow_back_black_24dp" />
38
+
39
+        <com.google.android.material.textview.MaterialTextView
40
+            android:id="@+id/materialTextView"
41
+            android:layout_width="wrap_content"
42
+            android:layout_height="wrap_content"
43
+            android:layout_marginStart="@dimen/_32sdp"
44
+            android:layout_marginTop="@dimen/_16sdp"
45
+            android:fontFamily="@font/open_sans_bold"
46
+            android:text="@string/settings"
47
+            android:textColor="@color/black_day_white_night"
48
+            android:textSize="@dimen/_22ssp"
49
+            app:layout_constraintStart_toEndOf="@+id/btn_back"
50
+            app:layout_constraintTop_toTopOf="parent" />
51
+
52
+        <ScrollView
53
+            android:layout_width="0dp"
54
+            android:layout_height="0dp"
55
+            android:layout_marginStart="@dimen/_16sdp"
56
+            android:layout_marginTop="@dimen/_16sdp"
57
+            android:layout_marginEnd="@dimen/_16sdp"
58
+            app:layout_constraintBottom_toBottomOf="parent"
59
+            app:layout_constraintEnd_toEndOf="parent"
60
+            app:layout_constraintStart_toStartOf="parent"
61
+            app:layout_constraintTop_toBottomOf="@+id/btn_back">
62
+
63
+            <androidx.constraintlayout.widget.ConstraintLayout
64
+                android:layout_width="match_parent"
65
+                android:layout_height="wrap_content">
66
+
67
+                <androidx.fragment.app.FragmentContainerView
68
+                    android:id="@+id/preference_fragment"
69
+                    android:name="com.certified.audionote.ui.PreferenceFragment"
70
+                    android:layout_width="0dp"
71
+                    android:layout_height="wrap_content"
72
+                    app:layout_constraintEnd_toEndOf="parent"
73
+                    app:layout_constraintStart_toStartOf="parent"
74
+                    app:layout_constraintTop_toTopOf="parent" />
75
+
76
+                <androidx.appcompat.widget.AppCompatImageView
77
+                    android:id="@+id/appCompatImageView4"
78
+                    android:layout_width="wrap_content"
79
+                    android:layout_height="wrap_content"
80
+                    android:layout_marginStart="@dimen/_12sdp"
81
+                    android:src="@drawable/ic_info_black_24dp"
82
+                    app:layout_constraintBottom_toBottomOf="@+id/materialTextView9"
83
+                    app:layout_constraintStart_toStartOf="parent"
84
+                    app:layout_constraintTop_toTopOf="@+id/materialTextView8" />
85
+
86
+                <com.google.android.material.textview.MaterialTextView
87
+                    android:id="@+id/materialTextView8"
88
+                    android:layout_width="wrap_content"
89
+                    android:layout_height="wrap_content"
90
+                    android:layout_marginStart="@dimen/_20sdp"
91
+                    android:layout_marginTop="@dimen/_8sdp"
92
+                    android:text="@string/about"
93
+                    android:fontFamily="@font/open_sans_semi_bold"
94
+                    android:textSize="@dimen/_14ssp"
95
+                    android:textColor="@color/black_day_white_night"
96
+                    app:layout_constraintStart_toEndOf="@+id/appCompatImageView4"
97
+                    app:layout_constraintTop_toBottomOf="@+id/preference_fragment" />
98
+
99
+                <com.google.android.material.textview.MaterialTextView
100
+                    android:id="@+id/materialTextView9"
101
+                    android:layout_width="wrap_content"
102
+                    android:layout_height="wrap_content"
103
+                    android:layout_marginBottom="@dimen/_4sdp"
104
+                    android:textSize="@dimen/_11ssp"
105
+                    android:fontFamily="@font/open_sans_regular"
106
+                    android:text=   "@string/app_version_licence_and_more"
107
+                    app:layout_constraintBottom_toBottomOf="parent"
108
+                    app:layout_constraintStart_toStartOf="@+id/materialTextView8"
109
+                    app:layout_constraintTop_toBottomOf="@+id/materialTextView8" />
110
+
111
+                <androidx.constraintlayout.widget.Group
112
+                    android:id="@+id/group_about"
113
+                    android:layout_width="0dp"
114
+                    android:layout_height="0dp"
115
+                    app:constraint_referenced_ids="materialTextView9,materialTextView8"
116
+                    app:layout_constraintBottom_toBottomOf="parent"
117
+                    app:layout_constraintEnd_toEndOf="parent"
118
+                    app:layout_constraintStart_toStartOf="parent"
119
+                    app:layout_constraintTop_toTopOf="@+id/materialTextView8" />
120
+
121
+            </androidx.constraintlayout.widget.ConstraintLayout>
122
+
123
+        </ScrollView>
124
+
125
+    </androidx.constraintlayout.widget.ConstraintLayout>
126
+</layout>
0 127
\ No newline at end of file
1 128
new file mode 100644
... ...
@@ -0,0 +1,185 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto"
19
+    xmlns:tools="http://schemas.android.com/tools">
20
+
21
+    <data>
22
+
23
+        <import type="com.certified.audionote.utils.Extensions" />
24
+
25
+        <import type="com.certified.audionote.utils.UtilKt" />
26
+
27
+        <variable
28
+            name="note"
29
+            type="com.certified.audionote.model.Note" />
30
+    </data>
31
+
32
+    <com.google.android.material.card.MaterialCardView
33
+        android:layout_width="match_parent"
34
+        android:layout_height="wrap_content"
35
+        app:cardBackgroundColor="@{note.color}"
36
+        app:cardCornerRadius="@dimen/_8sdp"
37
+        app:cardElevation="@dimen/_4sdp"
38
+        app:cardUseCompatPadding="true">
39
+
40
+        <androidx.constraintlayout.widget.ConstraintLayout
41
+            android:layout_width="match_parent"
42
+            android:layout_height="wrap_content"
43
+            android:background="@{note.color}"
44
+            android:paddingBottom="@dimen/_8sdp">
45
+
46
+            <com.google.android.material.textview.MaterialTextView
47
+                android:id="@+id/tv_note_title"
48
+                android:layout_width="0dp"
49
+                android:layout_height="wrap_content"
50
+                android:layout_marginStart="@dimen/_8sdp"
51
+                android:layout_marginTop="@dimen/_8sdp"
52
+                android:layout_marginEnd="@dimen/_4sdp"
53
+                android:ellipsize="end"
54
+                android:fontFamily="@font/open_sans_bold"
55
+                android:maxLines="1"
56
+                android:text="@{note.title}"
57
+                android:textColor="@color/white"
58
+                android:textSize="@dimen/_12ssp"
59
+                app:layout_constraintEnd_toStartOf="@+id/tv_note_last_modification_date"
60
+                app:layout_constraintHorizontal_bias="0.5"
61
+                app:layout_constraintHorizontal_chainStyle="spread_inside"
62
+                app:layout_constraintHorizontal_weight="4"
63
+                app:layout_constraintStart_toStartOf="parent"
64
+                app:layout_constraintTop_toTopOf="parent"
65
+                tools:text="CPE 407 - Lecture 1" />
66
+
67
+            <com.google.android.material.textview.MaterialTextView
68
+                android:id="@+id/tv_note_last_modification_date"
69
+                android:layout_width="0dp"
70
+                android:layout_height="wrap_content"
71
+                android:layout_marginEnd="@dimen/_8sdp"
72
+                android:ellipsize="end"
73
+                android:fontFamily="@font/open_sans_regular"
74
+                android:maxLines="1"
75
+                android:text="@{UtilKt.formatDate(note.lastModificationDate, context)}"
76
+                android:textAlignment="viewEnd"
77
+                android:textColor="@color/white"
78
+                android:textSize="@dimen/_10ssp"
79
+                app:layout_constraintBottom_toBottomOf="@+id/tv_note_title"
80
+                app:layout_constraintEnd_toEndOf="parent"
81
+                app:layout_constraintHorizontal_bias="0.5"
82
+                app:layout_constraintHorizontal_weight="2"
83
+                app:layout_constraintStart_toEndOf="@+id/tv_note_title"
84
+                app:layout_constraintTop_toTopOf="@+id/tv_note_title"
85
+                tools:text="17/11/21" />
86
+
87
+            <androidx.appcompat.widget.AppCompatImageButton
88
+                android:id="@+id/appCompatImageView"
89
+                android:layout_width="wrap_content"
90
+                android:layout_height="wrap_content"
91
+                android:layout_marginTop="@dimen/_8sdp"
92
+                android:background="@null"
93
+                android:padding="@dimen/_4sdp"
94
+                android:tint="@color/white"
95
+                app:layout_constraintEnd_toStartOf="@+id/tv_record_length"
96
+                app:layout_constraintHorizontal_bias="0.5"
97
+                app:layout_constraintHorizontal_chainStyle="spread_inside"
98
+                app:layout_constraintStart_toStartOf="parent"
99
+                app:layout_constraintTop_toBottomOf="@+id/tv_note_title"
100
+                app:srcCompat="@drawable/ic_mic_black_24dp" />
101
+
102
+            <com.google.android.material.textview.MaterialTextView
103
+                android:id="@+id/tv_record_length"
104
+                android:layout_width="wrap_content"
105
+                android:layout_height="wrap_content"
106
+                android:fontFamily="@font/open_sans_bold"
107
+                android:textColor="@color/white"
108
+                android:textSize="@dimen/_12ssp"
109
+                app:layout_constraintBottom_toBottomOf="@+id/appCompatImageView"
110
+                app:layout_constraintEnd_toStartOf="@+id/tv_note_size"
111
+                app:layout_constraintHorizontal_bias="0.5"
112
+                app:layout_constraintStart_toEndOf="@+id/appCompatImageView"
113
+                app:layout_constraintTop_toTopOf="@+id/appCompatImageView"
114
+                app:timeText="@{note.audioLength}"
115
+                tools:text="36:25" />
116
+
117
+            <com.google.android.material.textview.MaterialTextView
118
+                android:id="@+id/tv_note_size"
119
+                android:layout_width="wrap_content"
120
+                android:layout_height="wrap_content"
121
+                android:fontFamily="@font/open_sans_regular"
122
+                android:textColor="@color/white"
123
+                android:textSize="@dimen/_12ssp"
124
+                app:layout_constraintEnd_toEndOf="@+id/tv_note_last_modification_date"
125
+                app:layout_constraintHorizontal_bias="0.5"
126
+                app:layout_constraintStart_toEndOf="@+id/tv_record_length"
127
+                app:layout_constraintTop_toTopOf="@+id/tv_record_length"
128
+                app:sizeText="@{note.size}"
129
+                tools:text="46MB" />
130
+
131
+            <androidx.appcompat.widget.AppCompatImageButton
132
+                android:id="@+id/appCompatImageView2"
133
+                android:layout_width="wrap_content"
134
+                android:layout_height="wrap_content"
135
+                android:layout_marginTop="@dimen/_8sdp"
136
+                android:alpha=".6"
137
+                android:background="@null"
138
+                android:padding="@dimen/_4sdp"
139
+                android:tint="@color/white"
140
+                app:layout_constraintStart_toStartOf="@+id/appCompatImageView"
141
+                app:layout_constraintTop_toBottomOf="@+id/appCompatImageView"
142
+                app:srcCompat="@drawable/ic_alarm_on_black_24dp" />
143
+
144
+            <com.google.android.material.textview.MaterialTextView
145
+                android:id="@+id/tv_reminder_time"
146
+                android:layout_width="0dp"
147
+                android:layout_height="wrap_content"
148
+                android:layout_marginStart="@dimen/_4sdp"
149
+                android:alpha=".6"
150
+                android:ellipsize="end"
151
+                android:fontFamily="@font/open_sans_regular"
152
+                android:maxLines="1"
153
+                android:text="@{UtilKt.formatReminderDate(note.reminder)}"
154
+                android:textAlignment="textEnd"
155
+                android:textColor="@color/white"
156
+                android:textSize="@dimen/_12ssp"
157
+                app:layout_constraintBottom_toBottomOf="@+id/appCompatImageView2"
158
+                app:layout_constraintEnd_toEndOf="@+id/tv_note_size"
159
+                app:layout_constraintStart_toEndOf="@+id/appCompatImageView2"
160
+                app:layout_constraintTop_toTopOf="@+id/appCompatImageView2"
161
+                app:strikeThrough="@{UtilKt.currentDate().timeInMillis > note.reminder}"
162
+                app:visible="@{note.reminder != null}" />
163
+            <!--            tools:text="17 Nov, 2021 8:00 AM"-->
164
+
165
+            <com.google.android.material.textview.MaterialTextView
166
+                android:layout_width="0dp"
167
+                android:layout_height="wrap_content"
168
+                android:layout_marginStart="@dimen/_4sdp"
169
+                android:ellipsize="end"
170
+                android:fontFamily="@font/open_sans_regular"
171
+                android:maxLines="1"
172
+                android:text="@string/no_reminder_set"
173
+                android:textAlignment="viewEnd"
174
+                android:textColor="@color/white"
175
+                android:textSize="@dimen/_12ssp"
176
+                app:layout_constraintBottom_toBottomOf="@+id/appCompatImageView2"
177
+                app:layout_constraintEnd_toEndOf="@+id/tv_note_size"
178
+                app:layout_constraintStart_toEndOf="@+id/appCompatImageView2"
179
+                app:layout_constraintTop_toTopOf="@+id/appCompatImageView2"
180
+                app:visible="@{note.reminder == null}" />
181
+
182
+        </androidx.constraintlayout.widget.ConstraintLayout>
183
+
184
+    </com.google.android.material.card.MaterialCardView>
185
+</layout>
0 186
\ No newline at end of file
1 187
new file mode 100644
... ...
@@ -0,0 +1,94 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<layout xmlns:tools="http://schemas.android.com/tools"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto">
19
+
20
+    <data>
21
+
22
+        <variable
23
+            name="sliderItem"
24
+            type="com.certified.audionote.model.SliderItem" />
25
+    </data>
26
+
27
+    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
28
+        android:layout_width="match_parent"
29
+        android:layout_height="match_parent">
30
+
31
+        <androidx.appcompat.widget.AppCompatImageView
32
+            android:id="@+id/animation_view"
33
+            android:layout_width="0dp"
34
+            app:image="@{sliderItem.image}"
35
+            android:layout_height="0dp"
36
+            app:layout_constraintBottom_toTopOf="@+id/tv_title"
37
+            app:layout_constraintDimensionRatio="1:1"
38
+            app:layout_constraintEnd_toStartOf="@+id/guideline2"
39
+            app:layout_constraintHorizontal_bias="0.5"
40
+            app:layout_constraintStart_toStartOf="@+id/guideline"
41
+            app:layout_constraintTop_toTopOf="parent"
42
+            app:layout_constraintVertical_chainStyle="packed"/>
43
+
44
+        <TextView
45
+            android:id="@+id/tv_title"
46
+            android:fontFamily="@font/open_sans_bold_italic"
47
+            android:textColor="@color/titleText"
48
+            android:layout_width="0dp"
49
+            android:layout_height="wrap_content"
50
+            android:layout_marginTop="@dimen/_16sdp"
51
+            android:textAlignment="center"
52
+            android:text="@{sliderItem.title}"
53
+            android:textSize="@dimen/_18ssp"
54
+            app:layout_constraintBottom_toTopOf="@+id/tv_description"
55
+            app:layout_constraintEnd_toStartOf="@+id/guideline2"
56
+            app:layout_constraintHorizontal_bias="0.5"
57
+            app:layout_constraintStart_toStartOf="@+id/guideline"
58
+            app:layout_constraintTop_toBottomOf="@+id/animation_view"
59
+            tools:text="TextView" />
60
+
61
+        <TextView
62
+            android:id="@+id/tv_description"
63
+            android:textColor="@color/titleText"
64
+            android:fontFamily="@font/open_sans_medium_italic"
65
+            android:layout_width="0dp"
66
+            android:layout_height="wrap_content"
67
+            android:alpha=".7"
68
+            android:layout_marginTop="@dimen/_8sdp"
69
+            android:gravity="center"
70
+            android:text="@{sliderItem.description}"
71
+            android:textSize="@dimen/_12ssp"
72
+            app:layout_constraintBottom_toBottomOf="parent"
73
+            app:layout_constraintEnd_toStartOf="@+id/guideline2"
74
+            app:layout_constraintHorizontal_bias="0.5"
75
+            app:layout_constraintStart_toStartOf="@+id/guideline"
76
+            app:layout_constraintTop_toBottomOf="@+id/tv_title"
77
+            tools:text="TextView" />
78
+
79
+        <androidx.constraintlayout.widget.Guideline
80
+            android:id="@+id/guideline"
81
+            android:layout_width="wrap_content"
82
+            android:layout_height="wrap_content"
83
+            android:orientation="vertical"
84
+            app:layout_constraintGuide_percent="0.1" />
85
+
86
+        <androidx.constraintlayout.widget.Guideline
87
+            android:id="@+id/guideline2"
88
+            android:layout_width="wrap_content"
89
+            android:layout_height="wrap_content"
90
+            android:orientation="vertical"
91
+            app:layout_constraintGuide_percent="0.9" />
92
+
93
+    </androidx.constraintlayout.widget.ConstraintLayout>
94
+</layout>
0 95
\ No newline at end of file
1 96
new file mode 100644
... ...
@@ -0,0 +1,22 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
19
+    <background android:drawable="@color/ic_logo_background"/>
20
+    <foreground android:drawable="@drawable/ic_logo_foreground"/>
21
+    <monochrome android:drawable="@drawable/ic_logo" />
22
+</adaptive-icon>
0 23
\ No newline at end of file
1 24
new file mode 100644
... ...
@@ -0,0 +1,22 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
19
+    <background android:drawable="@color/ic_logo_background"/>
20
+    <foreground android:drawable="@drawable/ic_logo_foreground"/>
21
+    <monochrome android:drawable="@drawable/ic_logo" />
22
+</adaptive-icon>
0 23
\ No newline at end of file
1 24
new file mode 100644
2 25
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_logo.png differ
3 26
new file mode 100644
4 27
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_logo_round.png differ
5 28
new file mode 100644
6 29
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_logo.png differ
7 30
new file mode 100644
8 31
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_logo_round.png differ
9 32
new file mode 100644
10 33
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_logo.png differ
11 34
new file mode 100644
12 35
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_logo_round.png differ
13 36
new file mode 100644
14 37
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_logo.png differ
15 38
new file mode 100644
16 39
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_logo_round.png differ
17 40
new file mode 100644
18 41
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_logo.png differ
19 42
new file mode 100644
20 43
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_logo_round.png differ
21 44
new file mode 100644
... ...
@@ -0,0 +1,133 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<navigation xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto"
19
+    xmlns:tools="http://schemas.android.com/tools"
20
+    android:id="@+id/navigation"
21
+    app:startDestination="@id/onboardingFragment">
22
+
23
+    <fragment
24
+        android:id="@+id/homeFragment"
25
+        android:name="com.certified.audionote.ui.HomeFragment"
26
+        android:label="HomeFragment"
27
+        tools:layout="@layout/fragment_home">
28
+        <action
29
+            android:id="@+id/action_homeFragment_to_editNoteFragment"
30
+            app:destination="@id/editNoteFragment"
31
+            app:enterAnim="@anim/slide_in"
32
+            app:exitAnim="@anim/fade_out"
33
+            app:popEnterAnim="@anim/fade_in"
34
+            app:popExitAnim="@anim/slide_out"
35
+            app:popUpTo="@id/homeFragment"
36
+            app:popUpToInclusive="false" />
37
+        <action
38
+            android:id="@+id/action_homeFragment_to_addNoteFragment"
39
+            app:destination="@id/addNoteFragment"
40
+            app:enterAnim="@anim/slide_in"
41
+            app:exitAnim="@anim/fade_out"
42
+            app:popEnterAnim="@anim/fade_in"
43
+            app:popExitAnim="@anim/slide_out"
44
+            app:popUpTo="@id/homeFragment"
45
+            app:popUpToInclusive="false" />
46
+        <action
47
+            android:id="@+id/action_homeFragment_to_settingsFragment"
48
+            app:destination="@id/settingsFragment"
49
+            app:enterAnim="@anim/slide_in"
50
+            app:exitAnim="@anim/fade_out"
51
+            app:popEnterAnim="@anim/fade_in"
52
+            app:popExitAnim="@anim/slide_out"
53
+            app:popUpTo="@id/homeFragment"
54
+            app:popUpToInclusive="false" />
55
+    </fragment>
56
+    <fragment
57
+        android:id="@+id/editNoteFragment"
58
+        android:name="com.certified.audionote.ui.EditNoteFragment"
59
+        android:label="EditNoteFragment"
60
+        tools:layout="@layout/fragment_edit_note">
61
+        <action
62
+            android:id="@+id/action_editNoteFragment_to_homeFragment"
63
+            app:destination="@id/homeFragment"
64
+            app:enterAnim="@anim/fade_in"
65
+            app:exitAnim="@anim/slide_out"
66
+            app:popUpTo="@id/homeFragment"
67
+            app:popUpToInclusive="false" />
68
+        <argument
69
+            android:name="note"
70
+            app:argType="com.certified.audionote.model.Note" />
71
+    </fragment>
72
+    <fragment
73
+        android:id="@+id/addNoteFragment"
74
+        android:name="com.certified.audionote.ui.AddNoteFragment"
75
+        android:label="AddNoteFragment"
76
+        tools:layout="@layout/fragment_add_note">
77
+        <action
78
+            android:id="@+id/action_addNoteFragment_to_homeFragment"
79
+            app:destination="@id/homeFragment"
80
+            app:enterAnim="@anim/fade_in"
81
+            app:exitAnim="@anim/slide_out"
82
+            app:popUpTo="@id/homeFragment"
83
+            app:popUpToInclusive="false" />
84
+        <argument
85
+            android:name="note"
86
+            app:argType="com.certified.audionote.model.Note" />
87
+    </fragment>
88
+    <fragment
89
+        android:id="@+id/settingsFragment"
90
+        android:name="com.certified.audionote.features.settings.SettingsFragment"
91
+        android:label="SettingsFragment"
92
+        tools:layout="@layout/fragment_settings">
93
+        <action
94
+            android:id="@+id/action_settingsFragment_to_homeFragment"
95
+            app:destination="@id/homeFragment"
96
+            app:enterAnim="@anim/fade_in"
97
+            app:exitAnim="@anim/slide_out"
98
+            app:popUpTo="@id/homeFragment"
99
+            app:popUpToInclusive="true" />
100
+        <action
101
+            android:id="@+id/action_settingsFragment_to_aboutFragment"
102
+            app:destination="@id/aboutFragment"
103
+            app:enterAnim="@anim/slide_in"
104
+            app:exitAnim="@anim/fade_out"
105
+            app:popEnterAnim="@anim/fade_in"
106
+            app:popExitAnim="@anim/slide_out"
107
+            app:popUpTo="@id/settingsFragment" />
108
+    </fragment>
109
+    <fragment
110
+        android:id="@+id/aboutFragment"
111
+        android:name="com.certified.audionote.ui.AboutFragment"
112
+        android:label="fragment_about"
113
+        tools:layout="@layout/fragment_about">
114
+        <action
115
+            android:id="@+id/action_aboutFragment_to_settingsFragment"
116
+            app:destination="@id/settingsFragment"
117
+            app:enterAnim="@anim/fade_in"
118
+            app:exitAnim="@anim/slide_out"
119
+            app:popUpTo="@id/settingsFragment"
120
+            app:popUpToInclusive="true" />
121
+    </fragment>
122
+    <fragment
123
+        android:id="@+id/onboardingFragment"
124
+        android:name="com.certified.audionote.ui.OnboardingFragment"
125
+        android:label="fragment_onboarding"
126
+        tools:layout="@layout/fragment_onboarding" >
127
+        <action
128
+            android:id="@+id/action_onboardingFragment_to_homeFragment"
129
+            app:destination="@id/homeFragment"
130
+            app:popUpTo="@id/navigation"
131
+            app:popUpToInclusive="true" />
132
+    </fragment>
133
+</navigation>
0 134
\ No newline at end of file
1 135
new file mode 100644
... ...
@@ -0,0 +1,86 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources>
18
+    <string name="app_name">Audio Notes</string>
19
+    <string name="display">Visualizzazione</string>
20
+    <string name="theme">Tema</string>
21
+    <string name="choose_theme">Scegli tema</string>
22
+    <string name="description">Descrizione</string>
23
+    <string name="note_title_required">Titolo della nota (obbligatorio)</string>
24
+    <string name="new_note">Nuova Nota</string>
25
+    <string name="save">Salva</string>
26
+    <string name="add_note_button">Pulsante Aggiungi nota</string>
27
+    <string name="back_button">Pulsante Indietro</string>
28
+    <string name="delete_button">Pulsante Elimina</string>
29
+    <string name="share_button">Pulsante Condividi</string>
30
+    <string name="click_to_add_a_reminder_to_this_note">Aggiungi un promemoria a questa nota</string>
31
+    <string name="record_button">Registra</string>
32
+    <string name="reminder_button">Pulsante Promemoria</string>
33
+    <string name="welcome_back">Bentornato</string>
34
+    <string name="hi_there">Ehilà,</string>
35
+    <string name="your_record_list_is_empty_click_the_button_below_to_get_started">L\'elenco delle registrazioni è vuoto. Clicca sul pulsante in basso per iniziare</string>
36
+    <string name="about">Informazioni</string>
37
+    <string name="attributions_amp_licence">Attribuzioni e Licenze</string>
38
+    <string name="licenced_under_apache_licence_version_2_0">Rilasciato sotto Licenza Apache, Versione 2.0</string>
39
+    <string name="app_version_licence_and_more">Versione dell\'app, licenza e altro</string>
40
+    <string name="settings">Impostazioni</string>
41
+    <string name="edit_note">Modifica Nota</string>
42
+    <string name="alarm_icon">Icona Sveglia</string>
43
+    <string name="modify">Modifica</string>
44
+    <string name="delete">Elimina</string>
45
+    <string name="no_reminder_set">Nessun promemoria</string>
46
+    <string name="channelId">Notifica di Audio Notes</string>
47
+    <string name="view_pager_title_audio_recording">Registra audio facilmente</string>
48
+    <string name="view_pager_description_audio_recording">Prendere appunti non dovrebbe riguardare la digitazione o la scrittura da sole. Usa la funzione di registrazione vocale per registrare la tua nota in modo facile e veloce per migliorare la tua produttività</string>
49
+    <string name="view_pager_title_notification">Notifiche Personalizzate</string>
50
+    <string name="view_pager_description_notification">Imposta un promemoria per le tue note e ricevi una notifica all\'ora esatta per cui hai impostato il promemoria. Non devi più preoccuparti di dimenticare di controllare una nota.</string>
51
+    <string name="view_pager_title_dark_mode">Progettato per te</string>
52
+    <string name="view_pager_description_dark_mode">Prendere appunti non dovrebbe essere fantascienza. L\'app è stata progettata pensando a te per facilitare il modo in cui prendi appunti e anche per migliorare la tua produttività</string>
53
+    <string name="record_player">Registratore</string>
54
+    <string name="developer">Sviluppatore</string>
55
+    <string name="contribute">Contribuisci</string>
56
+    <string name="contribute_summary">Visualizza il progetto su GitHub</string>
57
+    <string name="contact_feedback">Contatto e Feedback</string>
58
+    <string name="get_started">Iniziamo</string>
59
+    <string name="just_now">Proprio ora</string>
60
+    <string name="a_minute_ago">un minuto fa</string>
61
+    <string name="minutes_ago">minuti fa</string>
62
+    <string name="an_hour_ago">un\'ora fa</string>
63
+    <string name="hours_ago">ore fa</string>
64
+    <string name="a_day_ago">un giorno fa</string>
65
+    <string name="theme_system_default">Predefinito di sistema</string>
66
+    <string name="theme_light">Chiaro</string>
67
+    <string name="theme_dark">Scuro</string>
68
+    <string name="now_playing">In riproduzione</string>
69
+    <string name="title_required">Il titolo della nota è obbligatorio</string>
70
+    <string name="permission_required">Questa autorizzazione è richiesta per abilitare le registrazioni audio</string>
71
+    <string name="note_saved">Nota salvata</string>
72
+    <string name="started_recording">Registrazione avviata</string>
73
+    <string name="stopped_recording">Registrazione terminata</string>
74
+    <string name="started_playing_recording">Riproduzione della registrazione avviata</string>
75
+    <string name="stopped_playing_recording">Riproduzione della registrazione terminata</string>
76
+    <string name="error_occurred">Si è verificato un errore</string>
77
+    <string name="yes">Sì</string>
78
+    <string name="no">No</string>
79
+    <string name="delete_note">Elimina Nota</string>
80
+    <string name="confirm_deletion">Sei sicuro di voler eliminare</string>
81
+    <string name="all">Tutte</string>
82
+    <string name="today">Oggi</string>
83
+    <string name="upcoming">Imminenti</string>
84
+    <string name="completed">Completate</string>
85
+    <string name="record_note_before_saving">Registra la tua nota audio prima di salvare</string>
86
+</resources>
0 87
\ No newline at end of file
1 88
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources>
18
+    <integer name="span_count">3</integer>
19
+</resources>
20
+
21
+    <!-- todo create ui constants for different screen sizes -->
0 22
\ No newline at end of file
1 23
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources>
18
+    <integer name="span_count">3</integer>
19
+</resources>
20
+
21
+    <!-- todo create ui constants for different screen sizes -->
0 22
\ No newline at end of file
1 23
new file mode 100644
... ...
@@ -0,0 +1,41 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<resources>
19
+    <color name="purple_200">#FFBB86FC</color>
20
+    <color name="purple_500">#FF6200EE</color>
21
+    <color name="purple_700">#FF3700B3</color>
22
+    <color name="teal_200">#FF03DAC5</color>
23
+    <color name="teal_700">#FF018786</color>
24
+    <color name="black">#FF000000</color>
25
+    <color name="white">#FFFFFFFF</color>
26
+
27
+    <color name="black_day_white_night">@color/white</color>
28
+    <color name="fragment_background">@color/primary</color>
29
+    <color name="other_fragment_background">@color/primary_darker</color>
30
+    <color name="primary">#313033</color>
31
+    <color name="primary_dark">#1C1B1F</color>
32
+    <color name="primary_darker">@color/black</color>
33
+    <color name="accent">@color/white</color>
34
+    <color name="mic_accent">#939094</color>
35
+    <color name="fab_background_tint">#EFB8C8</color>
36
+    <color name="about_icon_color">#939094</color>
37
+    <color name="edit_reminder_button_color">@color/about_icon_color</color>
38
+    <color name="grey">@color/white</color>
39
+    <color name="titleText">@color/white</color>
40
+    <color name="subtitleText">@color/white</color>
41
+</resources>
0 42
\ No newline at end of file
1 43
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources xmlns:tools="http://schemas.android.com/tools">
18
+    <!-- Base application theme. -->
19
+    <style name="Theme.AudioNote" parent="Theme.MaterialComponents.DayNight.NoActionBar">
20
+        <!-- Primary brand color. -->
21
+        <item name="colorPrimary">@color/primary</item>
22
+        <item name="colorPrimaryVariant">@color/primary_dark</item>
23
+        <item name="colorOnPrimary">@color/accent</item>
24
+        <!-- Secondary brand color. -->
25
+        <item name="colorSecondary">#D29DAC</item>
26
+        <item name="colorSecondaryVariant">@color/teal_200</item>
27
+        <item name="colorOnSecondary">@color/black</item>
28
+        <!-- Status bar color. -->
29
+        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
30
+        <!-- Customize your theme here. -->
31
+        <!--        <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>-->
32
+    </style>
33
+</resources>
0 34
\ No newline at end of file
1 35
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources>
18
+    <!-- Theme Preference -->
19
+    <string-array name="pref_theme">
20
+        <item>@string/theme_system_default</item>
21
+        <item>@string/theme_light</item>
22
+        <item>@string/theme_dark</item>
23
+    </string-array>
24
+
25
+    <string-array name="pref_theme_values">
26
+        <item>MODE_NIGHT_FOLLOW_SYSTEM</item>
27
+        <item>MODE_NIGHT_NO</item>
28
+        <item>MODE_NIGHT_YES</item>
29
+    </string-array>
30
+
31
+    <string-array name="filter_array">
32
+        <item>@string/all</item>
33
+        <item>@string/today</item>
34
+        <item>@string/upcoming</item>
35
+        <item>@string/completed</item>
36
+    </string-array>
37
+</resources>
0 38
\ No newline at end of file
1 39
new file mode 100644
... ...
@@ -0,0 +1,41 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<resources>
19
+    <color name="purple_200">#FFBB86FC</color>
20
+    <color name="purple_500">#FF6200EE</color>
21
+    <color name="purple_700">#FF3700B3</color>
22
+    <color name="teal_200">#FF03DAC5</color>
23
+    <color name="teal_700">#FF018786</color>
24
+    <color name="black">#FF000000</color>
25
+    <color name="white">#FFFFFFFF</color>
26
+
27
+    <color name="black_day_white_night">@color/black</color>
28
+    <color name="fragment_background">@color/accent</color>
29
+    <color name="other_fragment_background">@color/primary_darker</color>
30
+    <color name="primary">#EFB8C8</color>
31
+    <color name="primary_dark">#D29DAC</color>
32
+    <color name="primary_darker">#986977</color>
33
+    <color name="accent">#FFECF1</color>
34
+    <color name="mic_accent">#939094</color>
35
+    <color name="fab_background_tint">@color/primary</color>
36
+    <color name="about_icon_color">#EFB8C8</color>
37
+    <color name="edit_reminder_button_color">@color/other_fragment_background</color>
38
+    <color name="grey">#AEAEAE</color>
39
+    <color name="titleText">@color/primary_darker</color>
40
+    <color name="subtitleText">@color/primary_dark</color>
41
+</resources>
0 42
\ No newline at end of file
1 43
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<resources>
19
+    <color name="ic_logo_background">@color/primary</color>
20
+</resources>
0 21
\ No newline at end of file
1 22
new file mode 100644
... ...
@@ -0,0 +1,98 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources>
18
+    <string name="app_name">Audio Notes</string>
19
+    <string name="display">Display</string>
20
+    <string name="theme">Theme</string>
21
+    <string name="default_theme" translatable="false">MODE_NIGHT_FOLLOW_SYSTEM</string>
22
+    <string name="choose_theme">Choose theme</string>
23
+    <string name="key_theme" translatable="false">theme</string>
24
+    <string name="description">Description</string>
25
+    <string name="note_title_required">Note title (required)</string>
26
+    <string name="new_note">New Note</string>
27
+    <string name="save">Save</string>
28
+    <string name="add_note_button">Add note button</string>
29
+    <string name="back_button">Back button</string>
30
+    <string name="delete_button">Delete button</string>
31
+    <string name="share_button">Share button</string>
32
+    <string name="click_to_add_a_reminder_to_this_note">Click to add a reminder to this note</string>
33
+    <string name="record_button">Record</string>
34
+    <string name="reminder_button">Reminder button</string>
35
+    <string name="welcome_back">Welcome back</string>
36
+    <string name="hi_there">Hi there,</string>
37
+    <string name="your_record_list_is_empty_click_the_button_below_to_get_started">Your record list is empty. Click the button below to get started</string>
38
+    <string name="about">About</string>
39
+    <string name="app_version" translatable="false">v0.1.5.2(02052023)</string>
40
+    <string name="attributions_amp_licence"><![CDATA[Attributions & Licence]]></string>
41
+    <string name="licenced_under_apache_licence_version_2_0">Licenced under Apache Licence, Version 2.0</string>
42
+    <string name="app_version_licence_and_more">App version, Licence and more</string>
43
+    <string name="settings">Settings</string>
44
+    <string name="edit_note">Edit Note</string>
45
+    <string name="alarm_icon">Alarm Icon</string>
46
+    <string name="modify">Modify</string>
47
+    <string name="delete">Delete</string>
48
+    <string name="no_reminder_set">No reminder set</string>
49
+    <string name="channelId">Audio Notes notification</string>
50
+    <string name="view_pager_title_audio_recording">Record audio easily</string>
51
+    <string name="view_pager_description_audio_recording">Taking notes shouldn\'t be about typing or writing alone. Use the voice recording feature to record your note easily and faster to improve your productivity</string>
52
+    <string name="view_pager_title_notification">Custom Notifications</string>
53
+    <string name="view_pager_description_notification">Set a reminder for your notes and get notified at the exact time you set the reminder for.  You no longer have to worry about forgetting to check out a note.</string>
54
+    <string name="view_pager_title_dark_mode">Designed for you</string>
55
+    <string name="view_pager_description_dark_mode">Taking notes shouldn\'t be rocket science. The application was designed with you in mind to ease how you take notes and to also improve your productivity</string>
56
+    <string name="record_player">Record Player</string>
57
+    <string name="developer">Developer</string>
58
+    <string name="developer_nick" translatable="false">Sammie_kt</string>
59
+    <string name="contribute">Contribute</string>
60
+    <string name="contribute_summary">View project on Github</string>
61
+    <string name="developer_mail" translatable="false">Sammie_kt@pm.me</string>
62
+    <string name="contact_feedback"><![CDATA[Contact & Feedback]]></string>
63
+    <string name="get_started">Get Started</string>
64
+    <string name="just_now">Just now</string>
65
+    <string name="a_minute_ago">a minute ago</string>
66
+    <string name="minutes_ago">minutes ago</string>
67
+    <string name="an_hour_ago">an hour ago</string>
68
+    <string name="hours_ago">hours ago</string>
69
+    <string name="a_day_ago">a day ago</string>
70
+    <string name="theme_system_default">System default</string>
71
+    <string name="theme_light">Light</string>
72
+    <string name="theme_dark">Dark</string>
73
+    <string name="now_playing">Now playing</string>
74
+    <string name="title_required">The note title is required</string>
75
+    <string name="permission_required">This permission is required to enable audio recording</string>
76
+    <string name="note_saved">Note saved</string>
77
+    <string name="started_recording">Started recording</string>
78
+    <string name="stopped_recording">Stopped recording</string>
79
+    <string name="started_playing_recording">Started playing recording</string>
80
+    <string name="stopped_playing_recording">Stopped playing recording</string>
81
+    <string name="error_occurred">An error occurred</string>
82
+    <string name="yes">Yes</string>
83
+    <string name="no">No</string>
84
+    <string name="delete_note">Delete Note</string>
85
+    <string name="confirm_deletion">Are you sure you want to delete</string>
86
+    <string name="all">All</string>
87
+    <string name="today">Today</string>
88
+    <string name="upcoming">Upcoming</string>
89
+    <string name="completed">Completed</string>
90
+    <string name="record_note_before_saving">Please record your audio note before saving</string>
91
+    <string name="notification_permission_required" translatable="false">Notification permission is required to ensure you receive reminders for your saved notes</string>
92
+    <string name="notification_permission" translatable="false">Notification Permission</string>
93
+    <string name="audio_notes_channel" translatable="false">Audio Notes channel</string>
94
+    <string name="audio_record_permission" translatable="false">Audio record permission</string>
95
+    <string name="ok" translatable="false">OK</string>
96
+    <string name="file_not_found" translatable="false">File not found</string>
97
+    <string name="info_icon">Info Icon</string>
98
+</resources>
0 99
\ No newline at end of file
1 100
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources xmlns:tools="http://schemas.android.com/tools">
18
+    <!-- Base application theme. -->
19
+    <style name="Theme.AudioNote" parent="Theme.MaterialComponents.DayNight.NoActionBar">
20
+        <!-- Primary brand color. -->
21
+        <item name="colorPrimary">@color/primary</item>
22
+        <item name="colorPrimaryVariant">@color/primary_dark</item>
23
+        <item name="colorOnPrimary">@color/accent</item>
24
+        <!-- Secondary brand color. -->
25
+        <item name="colorSecondary">@color/primary_dark</item>
26
+        <item name="colorSecondaryVariant">@color/teal_700</item>
27
+        <item name="colorOnSecondary">@color/black</item>
28
+        <!-- Status bar color. -->
29
+        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
30
+        <!-- Customize your theme here. -->
31
+<!--        <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>-->
32
+    </style>
33
+
34
+    <style name="ShapeAppearanceOverlay.AudioNotes" parent="">
35
+        <item name="cornerSize">15%</item>
36
+    </style>
37
+
38
+</resources>
0 39
\ No newline at end of file
1 40
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+<?xml version="1.0" encoding="utf-8"?><!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<resources>
18
+    <integer name="span_count">2</integer>
19
+</resources>
20
+
21
+    <!-- todo create ui constants for different screen sizes -->
0 22
\ No newline at end of file
1 23
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+  ~ Copyright (c) 2023 Samson Achiaga
4
+  ~
5
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
6
+  ~ you may not use this file except in compliance with the License.
7
+  ~ You may obtain a copy of the License at
8
+  ~
9
+  ~     http://www.apache.org/licenses/LICENSE-2.0
10
+  ~
11
+  ~ Unless required by applicable law or agreed to in writing, software
12
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
13
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+  ~ See the License for the specific language governing permissions and
15
+  ~ limitations under the License.
16
+  -->
17
+
18
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
19
+    <external-path name="recordings" path="/" />
20
+</paths>
0 21
\ No newline at end of file
1 22
new file mode 100644
... ...
@@ -0,0 +1,72 @@
1
+<!--
2
+  ~ Copyright (c) 2023 Samson Achiaga
3
+  ~
4
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
5
+  ~ you may not use this file except in compliance with the License.
6
+  ~ You may obtain a copy of the License at
7
+  ~
8
+  ~     http://www.apache.org/licenses/LICENSE-2.0
9
+  ~
10
+  ~ Unless required by applicable law or agreed to in writing, software
11
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
12
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+  ~ See the License for the specific language governing permissions and
14
+  ~ limitations under the License.
15
+  -->
16
+
17
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
18
+    xmlns:app="http://schemas.android.com/apk/res-auto">
19
+
20
+    <PreferenceCategory app:title="@string/display">
21
+
22
+        <ListPreference
23
+            app:defaultValue="@string/default_theme"
24
+            app:dialogTitle="@string/choose_theme"
25
+            app:entries="@array/pref_theme"
26
+            app:entryValues="@array/pref_theme_values"
27
+            app:icon="@drawable/ic_brightness_medium_black_24dp"
28
+            app:key="@string/key_theme"
29
+            app:title="@string/theme"
30
+            app:useSimpleSummaryProvider="true" />
31
+
32
+    </PreferenceCategory>
33
+
34
+    <PreferenceCategory app:title="@string/about">
35
+        <Preference
36
+            android:icon="@drawable/ic_person_black_24"
37
+            app:summary="@string/developer_nick"
38
+            app:title="@string/developer">
39
+            <intent
40
+                android:action="android.intent.action.VIEW"
41
+                android:data="https://github.com/certified84" />
42
+        </Preference>
43
+
44
+        <Preference
45
+            android:icon="@drawable/ic_code_black_24dp"
46
+            app:summary="@string/contribute_summary"
47
+            app:title="@string/contribute">
48
+            <intent
49
+                android:action="android.intent.action.VIEW"
50
+                android:data="https://github.com/certified84/AudioNote" />
51
+        </Preference>
52
+
53
+        <Preference
54
+            android:icon="@drawable/ic_contact_support_black_24dp"
55
+            app:summary="@string/developer_mail"
56
+            app:title="@string/contact_feedback">
57
+            <intent
58
+                android:action="android.intent.action.SENDTO"
59
+                android:data="mailto:Sammie_kt@pm.me?subject=Feedback" />
60
+        </Preference>
61
+
62
+<!--        <Preference-->
63
+<!--            android:icon="@drawable/ic_info_black_24dp"-->
64
+<!--            app:summary="@string/app_version_licence_and_more"-->
65
+<!--            app:title="@string/about">-->
66
+<!--            <intent-->
67
+<!--                android:action="android.intent.action.VIEW"-->
68
+<!--                android:data="https://github.com/certified84/AudioNote" />-->
69
+<!--        </Preference>-->
70
+    </PreferenceCategory>
71
+
72
+</PreferenceScreen>
0 73
\ No newline at end of file
1 74
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+package com.certified.audionote
18
+
19
+import org.junit.Test
20
+
21
+import org.junit.Assert.*
22
+
23
+/**
24
+ * Example local unit test, which will execute on the development machine (host).
25
+ *
26
+ * See [testing documentation](http://d.android.com/tools/testing).
27
+ */
28
+class ExampleUnitTest {
29
+    @Test
30
+    fun addition_isCorrect() {
31
+        assertEquals(4, 2 + 2)
32
+    }
33
+}
0 34
\ No newline at end of file
1 35
new file mode 100644
... ...
@@ -0,0 +1,49 @@
1
+/*
2
+ * Copyright (c) 2023 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+plugins{
18
+    id("com.google.devtools.ksp") version "2.1.0-1.0.29" apply false
19
+}
20
+
21
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
22
+buildscript {
23
+    repositories {
24
+        google()
25
+        mavenCentral()
26
+        maven {url = uri("https://maven.google.com")}
27
+        maven { url = uri("https://jitpack.io") }
28
+    }
29
+    
30
+    dependencies {
31
+        classpath ("com.android.tools.build:gradle:8.7.3")
32
+        classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0")
33
+        classpath ("androidx.navigation:navigation-safe-args-gradle-plugin:2.8.5")
34
+        classpath ("com.google.dagger:hilt-android-gradle-plugin:2.53.1")
35
+        classpath("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
36
+
37
+        // NOTE: Do not place your application dependencies here; they belong
38
+        // in the individual module build.gradle files
39
+    }
40
+}
41
+
42
+allprojects {
43
+    repositories {
44
+        google()
45
+        mavenCentral()
46
+        maven {url = uri("https://maven.google.com")}
47
+        maven { url = uri("https://jitpack.io") }
48
+    }
49
+}
0 50
\ No newline at end of file
1 51
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+<i>AudioNotes</i> is a simple app allowing you to take voice recordings – a dictaphone. It supports light and dark theme, lets you save and edit your recordings.
0 2
new file mode 100644
1 3
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/icon.png differ
2 4
new file mode 100644
3 5
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/Screenshot_20220211-160800.png differ
4 6
new file mode 100644
5 7
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/Screenshot_20220211-160805.png differ
6 8
new file mode 100644
7 9
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/Screenshot_20220211-161703.png differ
8 10
new file mode 100644
9 11
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/about_dark.png differ
10 12
new file mode 100644
11 13
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/about_day.png differ
12 14
new file mode 100644
13 15
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/edit_note.png differ
14 16
new file mode 100644
15 17
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/home_dark.png differ
16 18
new file mode 100644
17 19
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/home_day.png differ
18 20
new file mode 100644
19 21
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/home_empty_dark.png differ
20 22
new file mode 100644
21 23
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/home_empty_day.png differ
22 24
new file mode 100644
23 25
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/new_note.png differ
24 26
new file mode 100644
25 27
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/onboarding_dark.png differ
26 28
new file mode 100644
27 29
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/onboarding_day.png differ
28 30
new file mode 100644
29 31
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/settings_dark.png differ
30 32
new file mode 100644
31 33
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/settings_day.png differ
32 34
new file mode 100644
33 35
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/splash_dark.png differ
34 36
new file mode 100644
35 37
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/splash_day.png differ
36 38
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+take audio notes (recordings)
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+#
2
+# Copyright (c) 2023 Samson Achiaga
3
+#
4
+# Licensed under the Apache License, Version 2.0 (the "License");
5
+# you may not use this file except in compliance with the License.
6
+# You may obtain a copy of the License at
7
+#
8
+#     http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+# Unless required by applicable law or agreed to in writing, software
11
+# distributed under the License is distributed on an "AS IS" BASIS,
12
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+# See the License for the specific language governing permissions and
14
+# limitations under the License.
15
+#
16
+
17
+# Project-wide Gradle settings.
18
+# IDE (e.g. Android Studio) users:
19
+# Gradle settings configured through the IDE *will override*
20
+# any settings specified in this file.
21
+# For more details on how to configure your build environment visit
22
+# http://www.gradle.org/docs/current/userguide/build_environment.html
23
+# Specifies the JVM arguments used for the daemon process.
24
+# The setting is particularly useful for tweaking memory settings.
25
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
26
+# When configured, Gradle will run in incubating parallel mode.
27
+# This option should only be used with decoupled projects. More details, visit
28
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
29
+# org.gradle.parallel=true
30
+# AndroidX package structure to make it clearer which packages are bundled with the
31
+# Android operating system, and which are packaged with your app"s APK
32
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
33
+android.useAndroidX=true
34
+# Automatically convert third-party libraries to use AndroidX
35
+android.enableJetifier=true
36
+# Kotlin code style for this project: "official" or "obsolete":
37
+kotlin.code.style=official
38
+android.nonTransitiveRClass=false
39
+android.nonFinalResIds=false
0 40
\ No newline at end of file
1 41
new file mode 100644
2 42
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
3 43
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+distributionBase=GRADLE_USER_HOME
2
+distributionPath=wrapper/dists
3
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
4
+networkTimeout=10000
5
+validateDistributionUrl=true
6
+zipStoreBase=GRADLE_USER_HOME
7
+zipStorePath=wrapper/dists
0 8
new file mode 100755
... ...
@@ -0,0 +1,249 @@
1
+#!/bin/sh
2
+
3
+#
4
+# Copyright © 2015-2021 the original authors.
5
+#
6
+# Licensed under the Apache License, Version 2.0 (the "License");
7
+# you may not use this file except in compliance with the License.
8
+# You may obtain a copy of the License at
9
+#
10
+#      https://www.apache.org/licenses/LICENSE-2.0
11
+#
12
+# Unless required by applicable law or agreed to in writing, software
13
+# distributed under the License is distributed on an "AS IS" BASIS,
14
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+# See the License for the specific language governing permissions and
16
+# limitations under the License.
17
+#
18
+
19
+##############################################################################
20
+#
21
+#   Gradle start up script for POSIX generated by Gradle.
22
+#
23
+#   Important for running:
24
+#
25
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26
+#       noncompliant, but you have some other compliant shell such as ksh or
27
+#       bash, then to run this script, type that shell name before the whole
28
+#       command line, like:
29
+#
30
+#           ksh Gradle
31
+#
32
+#       Busybox and similar reduced shells will NOT work, because this script
33
+#       requires all of these POSIX shell features:
34
+#         * functions;
35
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37
+#         * compound commands having a testable exit status, especially «case»;
38
+#         * various built-in commands including «command», «set», and «ulimit».
39
+#
40
+#   Important for patching:
41
+#
42
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
43
+#       by Bash, Ksh, etc; in particular arrays are avoided.
44
+#
45
+#       The "traditional" practice of packing multiple parameters into a
46
+#       space-separated string is a well documented source of bugs and security
47
+#       problems, so this is (mostly) avoided, by progressively accumulating
48
+#       options in "$@", and eventually passing that to Java.
49
+#
50
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52
+#       see the in-line comments for details.
53
+#
54
+#       There are tweaks for specific operating systems such as AIX, CygWin,
55
+#       Darwin, MinGW, and NonStop.
56
+#
57
+#   (3) This script is generated from the Groovy template
58
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59
+#       within the Gradle project.
60
+#
61
+#       You can find Gradle at https://github.com/gradle/gradle/.
62
+#
63
+##############################################################################
64
+
65
+# Attempt to set APP_HOME
66
+
67
+# Resolve links: $0 may be a link
68
+app_path=$0
69
+
70
+# Need this for daisy-chained symlinks.
71
+while
72
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
73
+    [ -h "$app_path" ]
74
+do
75
+    ls=$( ls -ld "$app_path" )
76
+    link=${ls#*' -> '}
77
+    case $link in             #(
78
+      /*)   app_path=$link ;; #(
79
+      *)    app_path=$APP_HOME$link ;;
80
+    esac
81
+done
82
+
83
+# This is normally unused
84
+# shellcheck disable=SC2034
85
+APP_BASE_NAME=${0##*/}
86
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
87
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
88
+
89
+# Use the maximum available, or set MAX_FD != -1 to use that value.
90
+MAX_FD=maximum
91
+
92
+warn () {
93
+    echo "$*"
94
+} >&2
95
+
96
+die () {
97
+    echo
98
+    echo "$*"
99
+    echo
100
+    exit 1
101
+} >&2
102
+
103
+# OS specific support (must be 'true' or 'false').
104
+cygwin=false
105
+msys=false
106
+darwin=false
107
+nonstop=false
108
+case "$( uname )" in                #(
109
+  CYGWIN* )         cygwin=true  ;; #(
110
+  Darwin* )         darwin=true  ;; #(
111
+  MSYS* | MINGW* )  msys=true    ;; #(
112
+  NONSTOP* )        nonstop=true ;;
113
+esac
114
+
115
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
116
+
117
+
118
+# Determine the Java command to use to start the JVM.
119
+if [ -n "$JAVA_HOME" ] ; then
120
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
121
+        # IBM's JDK on AIX uses strange locations for the executables
122
+        JAVACMD=$JAVA_HOME/jre/sh/java
123
+    else
124
+        JAVACMD=$JAVA_HOME/bin/java
125
+    fi
126
+    if [ ! -x "$JAVACMD" ] ; then
127
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
128
+
129
+Please set the JAVA_HOME variable in your environment to match the
130
+location of your Java installation."
131
+    fi
132
+else
133
+    JAVACMD=java
134
+    if ! command -v java >/dev/null 2>&1
135
+    then
136
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137
+
138
+Please set the JAVA_HOME variable in your environment to match the
139
+location of your Java installation."
140
+    fi
141
+fi
142
+
143
+# Increase the maximum file descriptors if we can.
144
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
145
+    case $MAX_FD in #(
146
+      max*)
147
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
148
+        # shellcheck disable=SC2039,SC3045
149
+        MAX_FD=$( ulimit -H -n ) ||
150
+            warn "Could not query maximum file descriptor limit"
151
+    esac
152
+    case $MAX_FD in  #(
153
+      '' | soft) :;; #(
154
+      *)
155
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
156
+        # shellcheck disable=SC2039,SC3045
157
+        ulimit -n "$MAX_FD" ||
158
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
159
+    esac
160
+fi
161
+
162
+# Collect all arguments for the java command, stacking in reverse order:
163
+#   * args from the command line
164
+#   * the main class name
165
+#   * -classpath
166
+#   * -D...appname settings
167
+#   * --module-path (only if needed)
168
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
169
+
170
+# For Cygwin or MSYS, switch paths to Windows format before running java
171
+if "$cygwin" || "$msys" ; then
172
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
173
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
174
+
175
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
176
+
177
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
178
+    for arg do
179
+        if
180
+            case $arg in                                #(
181
+              -*)   false ;;                            # don't mess with options #(
182
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
183
+                    [ -e "$t" ] ;;                      #(
184
+              *)    false ;;
185
+            esac
186
+        then
187
+            arg=$( cygpath --path --ignore --mixed "$arg" )
188
+        fi
189
+        # Roll the args list around exactly as many times as the number of
190
+        # args, so each arg winds up back in the position where it started, but
191
+        # possibly modified.
192
+        #
193
+        # NB: a `for` loop captures its iteration list before it begins, so
194
+        # changing the positional parameters here affects neither the number of
195
+        # iterations, nor the values presented in `arg`.
196
+        shift                   # remove old arg
197
+        set -- "$@" "$arg"      # push replacement arg
198
+    done
199
+fi
200
+
201
+
202
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
203
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
204
+
205
+# Collect all arguments for the java command:
206
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
207
+#     and any embedded shellness will be escaped.
208
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
209
+#     treated as '${Hostname}' itself on the command line.
210
+
211
+set -- \
212
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
213
+        -classpath "$CLASSPATH" \
214
+        org.gradle.wrapper.GradleWrapperMain \
215
+        "$@"
216
+
217
+# Stop when "xargs" is not available.
218
+if ! command -v xargs >/dev/null 2>&1
219
+then
220
+    die "xargs is not available"
221
+fi
222
+
223
+# Use "xargs" to parse quoted args.
224
+#
225
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
226
+#
227
+# In Bash we could simply go:
228
+#
229
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
230
+#   set -- "${ARGS[@]}" "$@"
231
+#
232
+# but POSIX shell has neither arrays nor command substitution, so instead we
233
+# post-process each arg (as a line of input to sed) to backslash-escape any
234
+# character that might be a shell metacharacter, then use eval to reverse
235
+# that process (while maintaining the separation between arguments), and wrap
236
+# the whole thing up as a single "set" statement.
237
+#
238
+# This will of course break if any of these variables contains a newline or
239
+# an unmatched quote.
240
+#
241
+
242
+eval "set -- $(
243
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
244
+        xargs -n1 |
245
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
246
+        tr '\n' ' '
247
+    )" '"$@"'
248
+
249
+exec "$JAVACMD" "$@"
0 250
new file mode 100644
... ...
@@ -0,0 +1,92 @@
1
+@rem
2
+@rem Copyright 2015 the original author or authors.
3
+@rem
4
+@rem Licensed under the Apache License, Version 2.0 (the "License");
5
+@rem you may not use this file except in compliance with the License.
6
+@rem You may obtain a copy of the License at
7
+@rem
8
+@rem      https://www.apache.org/licenses/LICENSE-2.0
9
+@rem
10
+@rem Unless required by applicable law or agreed to in writing, software
11
+@rem distributed under the License is distributed on an "AS IS" BASIS,
12
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+@rem See the License for the specific language governing permissions and
14
+@rem limitations under the License.
15
+@rem
16
+
17
+@if "%DEBUG%"=="" @echo off
18
+@rem ##########################################################################
19
+@rem
20
+@rem  Gradle startup script for Windows
21
+@rem
22
+@rem ##########################################################################
23
+
24
+@rem Set local scope for the variables with windows NT shell
25
+if "%OS%"=="Windows_NT" setlocal
26
+
27
+set DIRNAME=%~dp0
28
+if "%DIRNAME%"=="" set DIRNAME=.
29
+@rem This is normally unused
30
+set APP_BASE_NAME=%~n0
31
+set APP_HOME=%DIRNAME%
32
+
33
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
34
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35
+
36
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38
+
39
+@rem Find java.exe
40
+if defined JAVA_HOME goto findJavaFromJavaHome
41
+
42
+set JAVA_EXE=java.exe
43
+%JAVA_EXE% -version >NUL 2>&1
44
+if %ERRORLEVEL% equ 0 goto execute
45
+
46
+echo.
47
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48
+echo.
49
+echo Please set the JAVA_HOME variable in your environment to match the
50
+echo location of your Java installation.
51
+
52
+goto fail
53
+
54
+:findJavaFromJavaHome
55
+set JAVA_HOME=%JAVA_HOME:"=%
56
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57
+
58
+if exist "%JAVA_EXE%" goto execute
59
+
60
+echo.
61
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62
+echo.
63
+echo Please set the JAVA_HOME variable in your environment to match the
64
+echo location of your Java installation.
65
+
66
+goto fail
67
+
68
+:execute
69
+@rem Setup the command line
70
+
71
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72
+
73
+
74
+@rem Execute Gradle
75
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76
+
77
+:end
78
+@rem End local scope for the variables with windows NT shell
79
+if %ERRORLEVEL% equ 0 goto mainEnd
80
+
81
+:fail
82
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83
+rem the _cmd.exe /c_ return code!
84
+set EXIT_CODE=%ERRORLEVEL%
85
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
86
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87
+exit /b %EXIT_CODE%
88
+
89
+:mainEnd
90
+if "%OS%"=="Windows_NT" endlocal
91
+
92
+:omega
0 93
new file mode 100644
... ...
@@ -0,0 +1,18 @@
1
+/*
2
+ * Copyright (c) 2021 Samson Achiaga
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+rootProject.name = "Audio Note"
18
+include ':app'