├── fastlane
└── metadata
│ └── android
│ ├── de
│ ├── short_description.txt
│ └── full_description.txt
│ └── en-US
│ ├── short_description.txt
│ ├── images
│ ├── icon.png
│ ├── featureGraphic.png
│ └── phoneScreenshots
│ │ ├── 01.png
│ │ ├── 02.png
│ │ └── 03.png
│ └── full_description.txt
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── libs.versions.toml
├── app
├── src
│ ├── main
│ │ ├── ic_launcher-playstore.png
│ │ ├── res
│ │ │ ├── drawable
│ │ │ │ ├── juice_glass.png
│ │ │ │ ├── ic_rounded_alarm_on.xml
│ │ │ │ ├── ic_rounded_glass_cup.xml
│ │ │ │ ├── ic_juice_glass.xml
│ │ │ │ ├── ic_outline_water_full.xml
│ │ │ │ ├── ic_launcher_foreground.xml
│ │ │ │ ├── ic_outline_water_bottle.xml
│ │ │ │ └── no_custom_alarm.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── values
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ ├── themes.xml
│ │ │ │ └── colors.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── xml
│ │ │ │ ├── backup_rules.xml
│ │ │ │ └── data_extraction_rules.xml
│ │ │ └── values-zh-rCN
│ │ │ │ └── strings.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── criticalay
│ │ │ │ └── neer
│ │ │ │ ├── alarm
│ │ │ │ ├── custom_alarm
│ │ │ │ │ ├── CustomAlarmReceiver.kt
│ │ │ │ │ ├── CustomAlarmScheduler.kt
│ │ │ │ │ └── CustomAlarm.kt
│ │ │ │ └── default_alarm
│ │ │ │ │ ├── NeerAlarmManager.kt
│ │ │ │ │ ├── AlarmScheduler.kt
│ │ │ │ │ ├── data
│ │ │ │ │ ├── AlarmItem.kt
│ │ │ │ │ ├── AlarmDao.kt
│ │ │ │ │ └── NeerAlarmScheduler.kt
│ │ │ │ │ └── AlarmReceiver.kt
│ │ │ │ ├── notification
│ │ │ │ ├── NotificationItem.kt
│ │ │ │ ├── NeerNotification.kt
│ │ │ │ ├── WaterNotificationReceiver.kt
│ │ │ │ └── NeerNotificationService.kt
│ │ │ │ ├── data
│ │ │ │ ├── model
│ │ │ │ │ ├── Gender.kt
│ │ │ │ │ ├── Units.kt
│ │ │ │ │ ├── Beverage.kt
│ │ │ │ │ ├── User.kt
│ │ │ │ │ └── Intake.kt
│ │ │ │ ├── event
│ │ │ │ │ ├── BeverageEvent.kt
│ │ │ │ │ ├── NotificationEvent.kt
│ │ │ │ │ ├── NeerEvent.kt
│ │ │ │ │ ├── IntakeEvent.kt
│ │ │ │ │ └── UserEvent.kt
│ │ │ │ ├── dao
│ │ │ │ │ ├── BeverageDao.kt
│ │ │ │ │ ├── UserDao.kt
│ │ │ │ │ └── IntakeDao.kt
│ │ │ │ └── NeerDatabase.kt
│ │ │ │ ├── ui
│ │ │ │ ├── theme
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ ├── Type.kt
│ │ │ │ │ └── Theme.kt
│ │ │ │ ├── composables
│ │ │ │ │ ├── settings
│ │ │ │ │ │ ├── SettingItem.kt
│ │ │ │ │ │ └── items
│ │ │ │ │ │ │ ├── AppVersion.kt
│ │ │ │ │ │ │ ├── PrivacyPolicy.kt
│ │ │ │ │ │ │ ├── Units.kt
│ │ │ │ │ │ │ ├── BedTime.kt
│ │ │ │ │ │ │ ├── WakeUpTime.kt
│ │ │ │ │ │ │ └── Gender.kt
│ │ │ │ │ ├── userdetails
│ │ │ │ │ │ ├── DetailTextField.kt
│ │ │ │ │ │ ├── time
│ │ │ │ │ │ │ ├── WakeUpTimeItem.kt
│ │ │ │ │ │ │ ├── SleepTimeItem.kt
│ │ │ │ │ │ │ ├── WakupTimePicker.kt
│ │ │ │ │ │ │ └── SleepTimePicker.kt
│ │ │ │ │ │ ├── UnitItem.kt
│ │ │ │ │ │ └── GenderItem.kt
│ │ │ │ │ ├── CustomUI.kt
│ │ │ │ │ ├── home
│ │ │ │ │ │ ├── alertdialog
│ │ │ │ │ │ │ └── WaterAmountChip.kt
│ │ │ │ │ │ └── water
│ │ │ │ │ │ │ └── WaterRecordItem.kt
│ │ │ │ │ ├── notification
│ │ │ │ │ │ ├── NotificationIntervalSetting.kt
│ │ │ │ │ │ ├── NotificationSetting.kt
│ │ │ │ │ │ ├── CustomNotificationItem.kt
│ │ │ │ │ │ └── dialog
│ │ │ │ │ │ │ └── NotificationDialog.kt
│ │ │ │ │ ├── timepicker
│ │ │ │ │ │ ├── TimePickerDialog.kt
│ │ │ │ │ │ └── TimePickerWithDialog.kt
│ │ │ │ │ └── privacy
│ │ │ │ │ │ └── PrivacyScreen.kt
│ │ │ │ └── navigation
│ │ │ │ │ └── Destination.kt
│ │ │ │ ├── utils
│ │ │ │ ├── Constants.kt
│ │ │ │ ├── TimeUtils.kt
│ │ │ │ ├── AppUtils.kt
│ │ │ │ ├── UIUtils.kt
│ │ │ │ ├── Converters.kt
│ │ │ │ └── PreferencesManager.kt
│ │ │ │ ├── NeerActivity.kt
│ │ │ │ ├── di
│ │ │ │ └── DatabaseModule.kt
│ │ │ │ └── NeerApp.kt
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── criticalay
│ │ │ └── neer
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── criticalay
│ │ └── neer
│ │ └── ExampleInstrumentedTest.kt
├── proguard-rules.pro
└── .gitignore
├── .gitattributes
├── .idea
└── dictionaries
│ └── usernames.xml
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
└── pull_request_template
├── .gitignore
├── settings.gradle.kts
├── gradle.properties
├── gradlew.bat
└── README.md
/fastlane/metadata/android/de/short_description.txt:
--------------------------------------------------------------------------------
1 | Wasser-Erinnerung
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | Water Reminder
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/juice_glass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/drawable/juice_glass.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/featureGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/fastlane/metadata/android/en-US/images/featureGraphic.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.bat text
2 | *.csv text
3 | *.css text
4 | *.html text
5 | *.java text
6 | *.txt text
7 | *.xml text
8 | .idea/dictionaries/*.xml linguist-generated=false
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/01.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/02.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/criticalAY/Neer/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/03.png
--------------------------------------------------------------------------------
/.idea/dictionaries/usernames.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ashish
5 | Yadav
6 |
7 |
8 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 |
Neer is an Open-Source Water Reminder App Promoting Hydration and Wellness Without Compromising Privacy. Stay hydrated and healthy with Neer – your personal hydration assistant. Set goals, track your water intake, and achieve optimal hydration effortlessly.
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/full_description.txt:
--------------------------------------------------------------------------------
1 | Neer ist eine Open-Source-Wassererinnerungs-App, die Flüssigkeitszufuhr und Wohlbefinden fördert, ohne die Privatsphäre zu beeinträchtigen. Bleiben Sie hydriert und gesund mit Neer – Ihrem persönlichen Trinkassistenten. Setzen Sie sich Ziele, verfolgen Sie Ihre Wasseraufnahme und erreichen Sie mühelos eine optimale Flüssigkeitszufuhr.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ###### Reproduction Steps
11 |
12 | 1.
13 | 2.
14 | 3.
15 |
16 |
17 | ###### Expected Result
18 |
19 |
20 |
21 | ###### Actual Result
22 |
23 |
24 |
25 | ###### Debug info
26 |
27 | ###### Research
28 | *Enter an [x] character to confirm the points below:*
29 |
30 | - [ ] I have searched for similar existing issues here and on the user forum
31 | - [ ] (Optional) I have confirmed the issue is not resolved in the latest alpha release
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
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.
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
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/custom_alarm/CustomAlarmReceiver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.custom_alarm
18 |
19 | class CustomAlarmReceiver {
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/custom_alarm/CustomAlarmScheduler.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.custom_alarm
18 |
19 | class CustomAlarmScheduler {
20 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | #00BFFF
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/notification/NotificationItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.notification
18 |
19 | data class NotificationItem (
20 | val title:String,
21 | val message:String
22 | )
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/default_alarm/NeerAlarmManager.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.default_alarm
18 |
19 | import android.content.Context
20 |
21 | class NeerAlarmManager(val context: Context) {
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/model/Gender.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.model
18 |
19 | enum class Gender(val genderValue:String) {
20 | MALE("Male"),
21 | FEMALE("Female"),
22 | OTHER("Other")
23 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2024 Ashish Yadav
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 | #Thu Feb 15 15:39:22 IST 2024
18 | distributionBase=GRADLE_USER_HOME
19 | distributionPath=wrapper/dists
20 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
21 | zipStoreBase=GRADLE_USER_HOME
22 | zipStorePath=wrapper/dists
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/custom_alarm/CustomAlarm.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.custom_alarm
18 |
19 | import com.criticalay.neer.alarm.default_alarm.data.AlarmItem
20 |
21 | interface CustomAlarm {
22 | fun schedule(item: AlarmItem)
23 | fun cancel()
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/model/Units.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.model
18 |
19 | import com.criticalay.neer.utils.Converters
20 |
21 | enum class Units(override val unitValue: String): Converters.UnitProvider {
22 | KG_ML("kg/ml"),
23 | LBS_OZ("lbs/oz")
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/notification/NeerNotification.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.notification
18 |
19 | interface NeerNotification {
20 | fun showNotification(notificationItem: NotificationItem)
21 | fun showCustomNotification(notificationItem: NotificationItem)
22 | }
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/event/BeverageEvent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.event
18 |
19 | import com.criticalay.neer.data.model.Beverage
20 |
21 | sealed class BeverageEvent {
22 |
23 | data class AddBeverage(val beverage: Beverage) : BeverageEvent()
24 |
25 | data object GetTargetAmount: BeverageEvent()
26 |
27 | data class UpdateTarget(val target:Int) : BeverageEvent()
28 |
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/default_alarm/AlarmScheduler.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.default_alarm
18 |
19 | import com.criticalay.neer.alarm.default_alarm.data.AlarmItem
20 |
21 | interface AlarmScheduler {
22 | fun scheduleRegular(item: AlarmItem)
23 | fun scheduleOneTime(item: AlarmItem)
24 | fun scheduleRepeating(item: AlarmItem)
25 | fun cancel()
26 | fun cancelCustomAlarm(alarmId: Long)
27 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | #FFBB86FC
20 | #FF6200EE
21 | #FF3700B3
22 | #FF03DAC5
23 | #FF018786
24 | #FF000000
25 | #FFFFFFFF
26 |
--------------------------------------------------------------------------------
/app/src/test/java/com/criticalay/neer/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer
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 | }
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # built native files
12 | *.o
13 | *.so
14 |
15 | # generated files
16 | bin/
17 | gen/
18 |
19 | # Ignore gradle files
20 | .gradle/
21 | build/
22 |
23 | # Local configuration file (sdk path, etc)
24 | local.properties
25 |
26 | # Proguard folder generated by Eclipse
27 | proguard/
28 |
29 | # Eclipse Metadata
30 | .metadata/
31 |
32 | # Mac OS X clutter
33 | *.DS_Store
34 |
35 | # Windows clutter
36 | Thumbs.db
37 |
38 | # Ubunut gedit cluter
39 | *~
40 |
41 | # IDEA/Android Studio ignores
42 | *.iml
43 | *.ipr
44 | *.iws
45 | /.idea/*
46 | /captures
47 |
48 | # IDEA/Android Studio Ignore exceptions - this lets you share things you specifically want all team members to use
49 | !/.idea/codeStyles/
50 | # Keep dictionaries to have less false positives in spellcheck inspection.
51 | # Each user gets their own dictionary and these dictionaries are merged
52 | !.idea/dictionaries
53 | # IDEA/Android Studio project icon
54 | !/.idea/icon.svg
55 |
56 | #ignore the local insufficient memory for the Java Runtime Environment files
57 | hs_err_pid*
58 |
--------------------------------------------------------------------------------
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # built native files
12 | *.o
13 | *.so
14 |
15 | # generated files
16 | bin/
17 | gen/
18 |
19 | # Ignore gradle files
20 | .gradle/
21 | build/
22 |
23 | # Local configuration file (sdk path, etc)
24 | local.properties
25 |
26 | # Proguard folder generated by Eclipse
27 | proguard/
28 |
29 | # Eclipse Metadata
30 | .metadata/
31 |
32 | # Mac OS X clutter
33 | *.DS_Store
34 |
35 | # Windows clutter
36 | Thumbs.db
37 |
38 | # Ubunut gedit cluter
39 | *~
40 |
41 | # IDEA/Android Studio ignores
42 | *.iml
43 | *.ipr
44 | *.iws
45 | /.idea/*
46 | /captures
47 |
48 | /.idea/copyright
49 |
50 |
51 | # IDEA/Android Studio Ignore exceptions - this lets you share things you specifically want all team members to use
52 | !/.idea/codeStyles/
53 | # Keep dictionaries to have less false positives in spellcheck inspection.
54 | # Each user gets their own dictionary and these dictionaries are merged
55 | !.idea/dictionaries
56 | # IDEA/Android Studio project icon
57 | !/.idea/icon.svg
58 |
59 | #ignore the local insufficient memory for the Java Runtime Environment files
60 | hs_err_pid*
61 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # built native files
12 | *.o
13 | *.so
14 |
15 | # generated files
16 | bin/
17 | gen/
18 |
19 | # Ignore gradle files
20 | .gradle/
21 | build/
22 |
23 | app/release
24 |
25 | # Local configuration file (sdk path, etc)
26 | local.properties
27 |
28 | # Proguard folder generated by Eclipse
29 | proguard/
30 |
31 | # Eclipse Metadata
32 | .metadata/
33 |
34 | # Mac OS X clutter
35 | *.DS_Store
36 |
37 | # Windows clutter
38 | Thumbs.db
39 |
40 | # Ubunut gedit cluter
41 | *~
42 |
43 | # IDEA/Android Studio ignores
44 | *.iml
45 | *.ipr
46 | *.iws
47 | /.idea/*
48 | /captures
49 |
50 | /.idea/copyright
51 |
52 |
53 | # IDEA/Android Studio Ignore exceptions - this lets you share things you specifically want all team members to use
54 | !/.idea/codeStyles/
55 | # Keep dictionaries to have less false positives in spellcheck inspection.
56 | # Each user gets their own dictionary and these dictionaries are merged
57 | !.idea/dictionaries
58 | # IDEA/Android Studio project icon
59 | !/.idea/icon.svg
60 |
61 | #ignore the local insufficient memory for the Java Runtime Environment files
62 | hs_err_pid*
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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 |
18 | package com.criticalay.neer.ui.theme
19 |
20 | import androidx.compose.ui.graphics.Color
21 |
22 | // custom color
23 | val Light_blue = Color(0xFFA7C7E7)
24 | val Progress_Blue = Color(0xFF00BFFF)
25 | val GrayWhite = Color(0xFFF0F0F0)
26 |
27 |
28 | val BluePrimary = Color(0xFF00BFFF)
29 | val BlueSecondary = Color(0xFF007399)
30 | val BlueTertiary = Color(0xFF80DFFF)
31 |
32 | val DarkBluePrimary= Color(0xFF0099CC)
33 | val DarkBlueTertiary =Color(0xFF4695AF)
34 | val DarkBlueSecondary = Color(0xFF4E6472)
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
24 |
25 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/settings/SettingItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.settings
18 |
19 | import androidx.compose.foundation.layout.heightIn
20 | import androidx.compose.material3.Surface
21 | import androidx.compose.runtime.Composable
22 | import androidx.compose.ui.Modifier
23 | import androidx.compose.ui.unit.dp
24 |
25 | @Composable
26 | fun SettingItem(
27 | modifier: Modifier = Modifier,
28 | content: @Composable () -> Unit
29 | ) {
30 | Surface(
31 | modifier = modifier
32 | .heightIn(min = 56.dp)
33 | ) {
34 | content()
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/utils/Constants.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.utils
18 |
19 | object Constants {
20 | const val USER_DATABASE_TABLE = "user_table"
21 | const val NEER_DATABASE_NAME = "user_database"
22 |
23 | const val ALARM_DATABASE_TABLE = "alarm_table"
24 |
25 | const val BEVERAGE_DATABASE_TABLE = "beverage"
26 | const val INTAKE_DATABASE_TABLE = "intake"
27 | const val USER_ID =100L
28 | const val BEVERAGE_ID = 101L
29 |
30 | const val WATER_REMINDER_CHANNEL_ID = "neer_water_reminder_channel"
31 | const val CUSTOM_REMINDER_CHANNEL_ID = "neer_custom_reminder_channel"
32 | }
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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 | pluginManagement {
18 | repositories {
19 | google {
20 | content {
21 | includeGroupByRegex("com\\.android.*")
22 | includeGroupByRegex("com\\.google.*")
23 | includeGroupByRegex("androidx.*")
24 | }
25 | }
26 | mavenCentral()
27 | gradlePluginPortal()
28 | }
29 | }
30 | dependencyResolutionManagement {
31 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
32 | repositories {
33 | google()
34 | mavenCentral()
35 | }
36 | }
37 |
38 | rootProject.name = "Neer"
39 | include(":app")
40 |
--------------------------------------------------------------------------------
/.github/pull_request_template:
--------------------------------------------------------------------------------
1 |
2 | ## Purpose / Description
3 | _Describe the problem or feature and motivation_
4 |
5 | ## Fixes
6 | * Fixes _Link to the issues._
7 |
8 | ## Approach
9 | _How does this change address the problem?_
10 |
11 | ## How Has This Been Tested?
12 |
13 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration (SDK version(s), emulator or physical, etc)
14 |
15 | ## Learning (optional, can help others)
16 | _Describe the research stage_
17 |
18 | _Links to blog posts, patterns, libraries or addons used to solve this problem_
19 |
20 | ## Checklist
21 | _Please, go through these checks before submitting the PR._
22 |
23 | - [ ] You have a descriptive commit message with a short title (first line, max 50 chars).
24 | - [ ] You have commented your code, particularly in hard-to-understand areas
25 | - [ ] You have performed a self-review of your own code
26 | - [ ] UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
27 | - [ ] UI Changes: You have tested your change using the [Google Accessibility Scanner](https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor)
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/default_alarm/data/AlarmItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.default_alarm.data
18 |
19 | import androidx.room.Entity
20 | import androidx.room.PrimaryKey
21 | import com.criticalay.neer.utils.Constants.ALARM_DATABASE_TABLE
22 | import java.time.LocalDateTime
23 |
24 | @Entity(tableName = ALARM_DATABASE_TABLE)
25 | data class AlarmItem (
26 | val time: LocalDateTime,
27 | val interval:Double? = null,
28 | val title:String,
29 | val message:String,
30 | val repeating: Boolean = false,
31 | val alarmState: Boolean = true,
32 | @PrimaryKey(autoGenerate = true)
33 | val alarmId:Long = 0L
34 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/event/NotificationEvent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.event
18 |
19 | import com.criticalay.neer.alarm.default_alarm.data.AlarmItem
20 |
21 | sealed class NotificationEvent {
22 | data class SaveNotification(val notification: AlarmItem): NotificationEvent()
23 |
24 | data class UpdateNotification(val notification: AlarmItem): NotificationEvent()
25 |
26 | data class DeleteNotification(val notification: AlarmItem): NotificationEvent()
27 |
28 | data object GetAllScheduledNotifications: NotificationEvent()
29 |
30 | data class ToggleNotificationState(val alarmId:Long, val state:Boolean): NotificationEvent()
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/model/Beverage.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.model
18 |
19 | import androidx.room.Entity
20 | import androidx.room.ForeignKey
21 | import androidx.room.PrimaryKey
22 | import com.criticalay.neer.utils.Constants.BEVERAGE_DATABASE_TABLE
23 |
24 | @Entity(tableName = BEVERAGE_DATABASE_TABLE,
25 | foreignKeys = [
26 | ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"], onDelete = ForeignKey.CASCADE),
27 | ])
28 | data class Beverage(
29 | val userId:Long,
30 | val beverageName: String,
31 | val totalIntakeAmount : Int,
32 | @PrimaryKey
33 | val beverageId: Long = 101,
34 | )
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
22 |
23 |
24 |
28 |
29 |
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/model/User.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.model
18 |
19 | import androidx.room.Entity
20 | import androidx.room.PrimaryKey
21 | import com.criticalay.neer.utils.Constants.USER_DATABASE_TABLE
22 | import java.time.LocalTime
23 |
24 | @Entity(tableName = USER_DATABASE_TABLE)
25 | data class User(
26 | // No id field
27 | val name: String?= null,
28 | val age: Int? = null,
29 | val gender: Gender = Gender.FEMALE,
30 | val weight: Double = 0.0,
31 | val height: Double = 0.0,
32 | val bedTime: LocalTime?= null,
33 | val wakeUpTime: LocalTime?=null,
34 | val unit: Units = Units.KG_ML,
35 | @PrimaryKey
36 | val id: Long = 100
37 | )
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_rounded_alarm_on.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/event/NeerEvent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.event
18 |
19 | import com.criticalay.neer.data.model.Gender
20 | import com.criticalay.neer.data.model.Units
21 | import com.criticalay.neer.data.model.User
22 | import java.time.LocalTime
23 |
24 | sealed class NeerEvent {
25 | class AddUser(val user: User) : NeerEvent()
26 |
27 | data class TriggerIntakeEvent(val intakeEvent: IntakeEvent) : NeerEvent()
28 |
29 | data class TriggerUserEvent(val userEvent: UserEvent) : NeerEvent()
30 |
31 | data class TriggerBeverageEvent(val beverageEvent: BeverageEvent) : NeerEvent()
32 |
33 | data class TriggerNotificationEvent(val notificationEvent: NotificationEvent) : NeerEvent()
34 |
35 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_rounded_glass_cup.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/utils/TimeUtils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.utils
18 |
19 | import java.time.LocalDateTime
20 | import java.time.format.DateTimeFormatter
21 | import java.util.Locale
22 |
23 | object TimeUtils {
24 | fun formatLocalDateTimeToTime(dateTime: LocalDateTime): String {
25 | val time = dateTime.toLocalTime()
26 | val formattedTime = DateTimeFormatter.ofPattern("hh:mm a").format(time)
27 | return formattedTime
28 | }
29 |
30 | fun formatTime(hour: Int, minute: Int, isAm: Boolean): String {
31 | val formattedHour = if (hour > 12) hour - 12 else hour
32 | val amPm = if (hour >= 12) "PM" else "AM"
33 | return String.format(Locale.getDefault(), "%02d:%02d %s", formattedHour, minute, if (isAm) "AM" else "PM")
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/event/IntakeEvent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.event
18 |
19 | import com.criticalay.neer.data.model.Intake
20 | import java.time.LocalDateTime
21 |
22 | sealed class IntakeEvent {
23 |
24 | data class AddIntake(val intake:Intake) : IntakeEvent()
25 |
26 | data class GetTodayIntake(val startDay: LocalDateTime, val endDay:LocalDateTime): IntakeEvent()
27 |
28 | data class GetTodayTotalIntake(val startDay: LocalDateTime, val endDay:LocalDateTime): IntakeEvent()
29 |
30 | data class DeleteIntake(val intake: Intake):IntakeEvent()
31 |
32 | data class UpdateIntakeById(val intakeId:Long, val intakeAmount:Int) : IntakeEvent()
33 |
34 | // TODO: add them
35 | // data object DeleteIntake:IntakeEvent()
36 | // data object UpdateIntake:IntakeEvent()
37 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/criticalay/neer/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer
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.criticalay.neer", appContext.packageName)
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/utils/AppUtils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.utils
18 |
19 | import android.content.Context
20 | import com.criticalay.neer.R
21 |
22 | object AppUtils {
23 | val Context.isFreshInstall get() = with(packageManager.getPackageInfo(packageName, 0)) {
24 | firstInstallTime == lastUpdateTime
25 | }
26 |
27 | fun getRandomTitle(context: Context): String {
28 | val titles = context.resources.getStringArray(R.array.water_reminder_titles)
29 | val randomIndex = titles.indices.random()
30 | return titles[randomIndex]
31 | }
32 |
33 | fun getRandomMessage(context: Context): String {
34 | val messages = context.resources.getStringArray(R.array.water_reminder_messages)
35 | val randomIndex = messages.indices.random()
36 | return messages[randomIndex]
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_juice_glass.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/event/UserEvent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.event
18 |
19 | import com.criticalay.neer.data.model.Gender
20 | import com.criticalay.neer.data.model.Units
21 | import java.time.LocalTime
22 |
23 |
24 | sealed class UserEvent {
25 | data object GetUserDetails : UserEvent()
26 |
27 | data class UpdateUserName(val name: String) : UserEvent()
28 |
29 | data class UpdateUserAge(val age: Int) : UserEvent()
30 |
31 | data class UpdateUserWeight(val weight: Double) : UserEvent()
32 |
33 | data class UpdateUserHeight(val height: Double) :UserEvent()
34 |
35 | data class UpdateUserGender(val gender: Gender) :UserEvent()
36 |
37 | data class UpdateUserSleepTime(val bedTime: LocalTime) : UserEvent()
38 |
39 | data class UpdateUserWakeUpTime(val wakeUpTime: LocalTime) : UserEvent()
40 |
41 | data class UpdateUserUnits(val unit: Units) : UserEvent()
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/utils/UIUtils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.utils
18 |
19 | import android.content.Context
20 | import android.content.res.Resources
21 | import android.util.TypedValue
22 | import kotlin.math.ceil
23 |
24 |
25 | object UIUtils {
26 | val Int.dpf: Float
27 | get() {
28 | return dp.toFloat()
29 | }
30 |
31 |
32 | val Float.dpf: Float
33 | get() {
34 | return dp.toFloat()
35 | }
36 |
37 | val Int.dp: Int
38 | get() {
39 | return if (this == 0) {
40 | 0
41 | } else ceil((Resources.getSystem().displayMetrics.density * this).toDouble()).toInt()
42 | }
43 |
44 | val Float.dp: Int
45 | get() {
46 | return if (this == 0f) {
47 | 0
48 | } else ceil((Resources.getSystem().displayMetrics.density * this).toDouble()).toInt()
49 | }
50 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/dao/BeverageDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.dao
18 |
19 | import androidx.room.Dao
20 | import androidx.room.Insert
21 | import androidx.room.Query
22 | import com.criticalay.neer.data.model.Beverage
23 | import com.criticalay.neer.data.model.User
24 | import com.criticalay.neer.utils.Constants
25 | import com.criticalay.neer.utils.Constants.BEVERAGE_DATABASE_TABLE
26 | import com.criticalay.neer.utils.Constants.BEVERAGE_ID
27 | import kotlinx.coroutines.flow.Flow
28 |
29 | @Dao
30 | interface BeverageDao {
31 | @Insert
32 | suspend fun insertBeverage(beverage: Beverage)
33 |
34 | @Query("SELECT totalIntakeAmount FROM $BEVERAGE_DATABASE_TABLE")
35 | fun getTotalIntakeAmount(): Flow
36 |
37 | @Query("UPDATE $BEVERAGE_DATABASE_TABLE SET totalIntakeAmount = :newTotalIntakeAmount WHERE beverageId = $BEVERAGE_ID")
38 | suspend fun updateTotalIntakeAmount(newTotalIntakeAmount: Int)
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/notification/WaterNotificationReceiver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.notification
18 |
19 | import android.app.Application
20 | import android.app.NotificationManager
21 | import android.content.BroadcastReceiver
22 | import android.content.Context
23 | import android.content.Intent
24 | import androidx.lifecycle.ViewModelProvider
25 | import com.criticalay.neer.data.event.IntakeEvent
26 | import com.criticalay.neer.data.event.NeerEvent
27 | import com.criticalay.neer.data.model.Intake
28 | import com.criticalay.neer.ui.viewmodel.SharedViewModel
29 | import com.criticalay.neer.utils.Constants
30 | import com.criticalay.neer.utils.PreferencesManager
31 | import java.time.LocalDateTime
32 |
33 | class WaterNotificationReceiver:BroadcastReceiver() {
34 | override fun onReceive(context: Context, intent: Intent?) {
35 | // TODO: we want to add the button in the notification itself to update the water amount
36 | }
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/navigation/Destination.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.navigation
18 |
19 | sealed class Destination(val path: String) {
20 | data object HomeScreen : Destination("home")
21 |
22 | data object UserDetails : Destination("userDetails")
23 |
24 | data object WaterDetails : Destination("waterDetails")
25 |
26 | data object Settings : Destination("settings")
27 |
28 | data object Notification : Destination("notifications")
29 |
30 | data object Privacy : Destination("privacy")
31 |
32 | data object Onboarding : Destination("onboarding")
33 |
34 | companion object {
35 | fun fromString(route: String): Destination {
36 | return when (route) {
37 | Settings.path -> Settings
38 | UserDetails.path -> UserDetails
39 | WaterDetails.path -> WaterDetails
40 | else -> HomeScreen
41 | }
42 |
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/model/Intake.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.model
18 |
19 | import androidx.room.Entity
20 | import androidx.room.ForeignKey
21 | import androidx.room.PrimaryKey
22 | import com.criticalay.neer.utils.Constants.INTAKE_DATABASE_TABLE
23 | import java.time.LocalDateTime
24 |
25 | @Entity(tableName = INTAKE_DATABASE_TABLE,
26 | foreignKeys = [
27 | ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"], onDelete = ForeignKey.CASCADE),
28 | ForeignKey(entity = Beverage::class, parentColumns = ["beverageId"], childColumns = ["beverageId"], onDelete = ForeignKey.CASCADE)
29 | ]
30 | )
31 | data class Intake(
32 | val userId: Long, // Foreign key reference to User
33 | val beverageId: Long, // Foreign key reference to Beverage
34 | val intakeAmount: Int,
35 | val intakeDateTime: LocalDateTime, // Using LocalDateTime for simplicity
36 | @PrimaryKey(autoGenerate = true)
37 | val intakeId: Long = 0,
38 | )
39 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_water_full.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/default_alarm/data/AlarmDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.default_alarm.data
18 |
19 | import androidx.room.Dao
20 | import androidx.room.Delete
21 | import androidx.room.Insert
22 | import androidx.room.OnConflictStrategy
23 | import androidx.room.Query
24 | import androidx.room.Update
25 | import com.criticalay.neer.utils.Constants.ALARM_DATABASE_TABLE
26 | import kotlinx.coroutines.flow.Flow
27 |
28 | @Dao
29 | interface AlarmDao {
30 |
31 | @Query("SELECT * FROM $ALARM_DATABASE_TABLE")
32 | fun getAllAlarms(): Flow>?
33 |
34 | @Insert(onConflict = OnConflictStrategy.IGNORE)
35 | suspend fun insertAlarm(alarmItem: AlarmItem)
36 |
37 | @Update
38 | suspend fun updateAlarm(alarmItem: AlarmItem)
39 |
40 | @Delete
41 | suspend fun deleteAlarm(alarmItem: AlarmItem)
42 |
43 | @Query("UPDATE $ALARM_DATABASE_TABLE SET alarmState = :state WHERE alarmId = :alarmId")
44 | suspend fun toggleAlarmState(alarmId: Long, state: Boolean)
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.theme
18 |
19 | import androidx.compose.material3.Typography
20 | import androidx.compose.ui.text.TextStyle
21 | import androidx.compose.ui.text.font.FontFamily
22 | import androidx.compose.ui.text.font.FontWeight
23 | import androidx.compose.ui.unit.sp
24 |
25 | // Set of Material typography styles to start with
26 | val Typography = Typography(
27 | bodyLarge = TextStyle(
28 | fontFamily = FontFamily.Default,
29 | fontWeight = FontWeight.Normal,
30 | fontSize = 16.sp,
31 | lineHeight = 24.sp,
32 | letterSpacing = 0.5.sp
33 | )
34 | /* Other default text styles to override
35 | titleLarge = TextStyle(
36 | fontFamily = FontFamily.Default,
37 | fontWeight = FontWeight.Normal,
38 | fontSize = 22.sp,
39 | lineHeight = 28.sp,
40 | letterSpacing = 0.sp
41 | ),
42 | labelSmall = TextStyle(
43 | fontFamily = FontFamily.Default,
44 | fontWeight = FontWeight.Medium,
45 | fontSize = 11.sp,
46 | lineHeight = 16.sp,
47 | letterSpacing = 0.5.sp
48 | )
49 | */
50 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/NeerActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer
18 |
19 | import android.os.Bundle
20 | import androidx.activity.ComponentActivity
21 | import androidx.activity.compose.setContent
22 | import androidx.activity.enableEdgeToEdge
23 | import androidx.lifecycle.viewmodel.compose.viewModel
24 | import androidx.navigation.compose.rememberNavController
25 | import com.criticalay.neer.ui.navigation.Navigation
26 | import com.criticalay.neer.ui.theme.NeerTheme
27 | import com.criticalay.neer.ui.viewmodel.SharedViewModel
28 | import dagger.hilt.android.AndroidEntryPoint
29 |
30 | @AndroidEntryPoint
31 | class NeerActivity : ComponentActivity() {
32 | override fun onCreate(savedInstanceState: Bundle?) {
33 | super.onCreate(savedInstanceState)
34 | enableEdgeToEdge()
35 | setContent {
36 | NeerTheme {
37 | val navController = rememberNavController()
38 | val viewModel: SharedViewModel = viewModel()
39 | Navigation(
40 | navController = navController,
41 | sharedViewModel = viewModel
42 | )
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/utils/Converters.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.utils
18 |
19 | import androidx.room.TypeConverter
20 | import java.time.LocalDate
21 | import java.time.LocalDateTime
22 | import java.time.LocalTime
23 | import java.time.ZoneOffset
24 |
25 | object Converters {
26 | @TypeConverter
27 | fun fromTimestamp(value: Long?): LocalDateTime? {
28 | return value?.let { LocalDateTime.ofEpochSecond(it, 0, ZoneOffset.UTC) }
29 | }
30 |
31 | @TypeConverter
32 | fun dateToTimestamp(date: LocalDateTime?): Long? {
33 | return date?.toEpochSecond(ZoneOffset.UTC)
34 | }
35 |
36 | @TypeConverter
37 | @JvmStatic
38 | fun fromTime(time: LocalTime?): String? {
39 | return time?.toString()
40 | }
41 |
42 | @TypeConverter
43 | @JvmStatic
44 | fun toTime(timeStr: String?): LocalTime? {
45 | return timeStr?.let { LocalTime.parse(it) }
46 | }
47 |
48 | interface UnitProvider {
49 | val unitValue: String
50 | }
51 |
52 | inline fun getUnitName(unit: T, index: Int): String where T : Enum, T : UnitProvider {
53 | val unitValue = (unit as UnitProvider).unitValue
54 | return unitValue.split("/")[index]
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
23 |
27 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/di/DatabaseModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.di
18 |
19 | import android.content.Context
20 | import androidx.room.Room
21 | import com.criticalay.neer.data.NeerDatabase
22 | import com.criticalay.neer.utils.Constants.NEER_DATABASE_NAME
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 | @Module
31 | @InstallIn(SingletonComponent::class)
32 | object DatabaseModule {
33 |
34 | @Provides
35 | @Singleton
36 | fun provideDatabase(@ApplicationContext context: Context) =
37 | Room.databaseBuilder(
38 | context = context,
39 | NeerDatabase::class.java,
40 | NEER_DATABASE_NAME
41 | ).addMigrations(NeerDatabase.MIGRATION_1_2).build()
42 |
43 | @Provides
44 | @Singleton
45 | fun provideUserDao(database: NeerDatabase) = database.userDao()
46 |
47 | @Provides
48 | @Singleton
49 | fun provideBeverageDao(database: NeerDatabase) = database.beverageDao()
50 |
51 | @Provides
52 | @Singleton
53 | fun provideIntakeDao(database: NeerDatabase) = database.intakeDao()
54 |
55 | @Provides
56 | @Singleton
57 | fun provideAlarmDao(database: NeerDatabase) = database.alarmDao()
58 |
59 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2024 Ashish Yadav
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. For more details, visit
28 | # https://developer.android.com/r/tools/gradle-multi-project-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 | # Kotlin code style for this project: "official" or "obsolete":
35 | kotlin.code.style=official
36 | # Enables namespacing of each library's R class so that its R class includes only the
37 | # resources declared in the library itself and none from the library's dependencies,
38 | # thereby reducing the size of the R class for that library
39 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/userdetails/DetailTextField.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.userdetails
18 |
19 | import androidx.compose.foundation.text.KeyboardActions
20 | import androidx.compose.foundation.text.KeyboardOptions
21 | import androidx.compose.material3.OutlinedTextField
22 | import androidx.compose.material3.Text
23 | import androidx.compose.runtime.Composable
24 | import androidx.compose.ui.Modifier
25 | import kotlin.math.sin
26 |
27 | @Composable
28 | fun DetailTextField(
29 | value: String,
30 | onValueChange: (String) -> Unit,
31 | modifier: Modifier = Modifier,
32 | label: String = "",
33 | placeholder: String = "",
34 | trailingIcon: @Composable (() -> Unit)? = null,
35 | leadingIcon: @Composable (() -> Unit)? = null,
36 | keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
37 | keyboardActions: KeyboardActions = KeyboardActions.Default,
38 | singleLine:Boolean = true
39 | ) {
40 | OutlinedTextField(
41 | value = value,
42 | onValueChange = onValueChange,
43 | modifier = modifier,
44 | label = { Text(text = label) },
45 | placeholder = { Text(text = placeholder) },
46 | trailingIcon = trailingIcon,
47 | leadingIcon = leadingIcon,
48 | maxLines = 1,
49 | singleLine = singleLine,
50 | keyboardOptions = keyboardOptions,
51 | keyboardActions = keyboardActions
52 | )
53 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_water_bottle.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
20 |
21 |
22 |
23 |
24 |
36 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/userdetails/time/WakeUpTimeItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.userdetails.time
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.padding
22 | import androidx.compose.material3.Text
23 | import androidx.compose.runtime.Composable
24 | import androidx.compose.ui.Alignment
25 | import androidx.compose.ui.Modifier
26 | import androidx.compose.ui.res.stringResource
27 | import androidx.compose.ui.unit.dp
28 | import androidx.compose.ui.unit.sp
29 | import com.criticalay.neer.R
30 | import com.criticalay.neer.ui.composables.settings.SettingItem
31 |
32 | @Composable
33 | fun WakeUpTimeItem(
34 | modifier: Modifier = Modifier,
35 | title: String,
36 | setTime : String,
37 | onSettingClicked: () -> Unit,
38 | ) {
39 | SettingItem(modifier = modifier) {
40 | Row(
41 | modifier = Modifier.run {
42 | clickable(
43 | onClickLabel = stringResource(R.string.select_wake_up_time)
44 | ) {
45 | onSettingClicked()
46 | }
47 | .padding(horizontal = 16.dp)
48 | },
49 | verticalAlignment = Alignment.CenterVertically
50 | ) {
51 | Text(
52 | text = title,
53 | modifier = Modifier
54 | .weight(1f),
55 | fontSize = 18.sp
56 | )
57 | Text(
58 | text = setTime,
59 | fontSize = 18.sp
60 | )
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/settings/items/AppVersion.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.settings.items
18 |
19 | import androidx.compose.foundation.layout.Row
20 | import androidx.compose.foundation.layout.padding
21 | import androidx.compose.material.icons.Icons
22 | import androidx.compose.material.icons.rounded.Info
23 | import androidx.compose.material.icons.rounded.Support
24 | import androidx.compose.material3.Icon
25 | import androidx.compose.material3.Text
26 | import androidx.compose.runtime.Composable
27 | import androidx.compose.ui.Alignment
28 | import androidx.compose.ui.Modifier
29 | import androidx.compose.ui.res.stringResource
30 | import androidx.compose.ui.semantics.semantics
31 | import androidx.compose.ui.unit.dp
32 | import androidx.compose.ui.unit.sp
33 | import com.criticalay.neer.R
34 | import com.criticalay.neer.ui.composables.settings.SettingItem
35 |
36 | @Composable
37 | fun AppVersionSettingItem(
38 | modifier: Modifier = Modifier,
39 | appVersion:String
40 | ){
41 | SettingItem(modifier= modifier) {
42 | Row(
43 | modifier = Modifier
44 | .semantics(mergeDescendants = true){}
45 | .padding(horizontal = 16.dp),
46 | verticalAlignment = Alignment.CenterVertically
47 | ){
48 | Icon(
49 | modifier = Modifier.padding(end = 5.dp),
50 | imageVector = Icons.Rounded.Info,
51 | contentDescription = null
52 | )
53 | Text(
54 | modifier = Modifier.weight(1f).padding(start = 5.dp),
55 | fontSize = 18.sp,
56 | text = stringResource(id = R.string.setting_app_version_title))
57 |
58 | Text(
59 | fontSize = 18.sp,
60 | text = appVersion)
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/userdetails/time/SleepTimeItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.userdetails.time
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.padding
22 | import androidx.compose.material.icons.Icons
23 | import androidx.compose.material.icons.filled.KeyboardArrowRight
24 | import androidx.compose.material3.Icon
25 | import androidx.compose.material3.IconButton
26 | import androidx.compose.material3.Text
27 | import androidx.compose.runtime.Composable
28 | import androidx.compose.ui.Alignment
29 | import androidx.compose.ui.Modifier
30 | import androidx.compose.ui.res.stringResource
31 | import androidx.compose.ui.unit.dp
32 | import androidx.compose.ui.unit.sp
33 | import com.criticalay.neer.R
34 | import com.criticalay.neer.ui.composables.settings.SettingItem
35 |
36 |
37 | @Composable
38 | fun SleepTimeItem(
39 | modifier: Modifier = Modifier,
40 | title: String,
41 | setTime : String,
42 | onSettingClicked: () -> Unit,
43 | ) {
44 | SettingItem(modifier = modifier) {
45 | Row(
46 | modifier = with(Modifier) {
47 | clickable(
48 | onClickLabel = stringResource(R.string.select_sleep_time)
49 | ) {
50 | onSettingClicked()
51 | }
52 | .padding(horizontal = 16.dp)
53 | },
54 | verticalAlignment = Alignment.CenterVertically
55 | ) {
56 | Text(
57 | text = title,
58 | modifier = Modifier
59 | .weight(1f),
60 | fontSize = 18.sp
61 | )
62 | Text(
63 | text = setTime,
64 | fontSize = 18.sp
65 | )
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/settings/items/PrivacyPolicy.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.settings.items
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.padding
22 | import androidx.compose.material.icons.Icons
23 | import androidx.compose.material.icons.rounded.PrivacyTip
24 | import androidx.compose.material.icons.rounded.Support
25 | import androidx.compose.material3.Icon
26 | import androidx.compose.material3.Text
27 | import androidx.compose.runtime.Composable
28 | import androidx.compose.ui.Alignment
29 | import androidx.compose.ui.Modifier
30 | import androidx.compose.ui.res.stringResource
31 | import androidx.compose.ui.semantics.semantics
32 | import androidx.compose.ui.unit.dp
33 | import androidx.compose.ui.unit.sp
34 | import com.criticalay.neer.R
35 | import com.criticalay.neer.ui.composables.settings.SettingItem
36 |
37 | @Composable
38 | fun PrivacyPolicy(
39 | modifier: Modifier = Modifier,
40 | handleClick: () -> Unit
41 | ) {
42 | SettingItem(modifier = modifier .clickable {
43 | handleClick()
44 | }) {
45 | Row(
46 | modifier = Modifier
47 | .semantics(mergeDescendants = true) {}
48 | .padding(horizontal = 16.dp),
49 | verticalAlignment = Alignment.CenterVertically
50 | ) {
51 | Icon(
52 | modifier = Modifier.padding(end = 5.dp),
53 | imageVector = Icons.Rounded.PrivacyTip,
54 | contentDescription = null
55 | )
56 | Text(
57 | modifier = Modifier
58 | .weight(1f).padding(start = 5.dp),
59 | fontSize = 18.sp,
60 | text = stringResource(R.string.privacy_policy)
61 | )
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/CustomUI.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables
18 |
19 | import androidx.compose.foundation.background
20 | import androidx.compose.foundation.layout.Box
21 | import androidx.compose.foundation.layout.Column
22 | import androidx.compose.foundation.layout.fillMaxWidth
23 | import androidx.compose.foundation.layout.height
24 | import androidx.compose.foundation.layout.padding
25 | import androidx.compose.material3.MaterialTheme
26 | import androidx.compose.material3.Text
27 | import androidx.compose.runtime.Composable
28 | import androidx.compose.ui.Alignment
29 | import androidx.compose.ui.Modifier
30 | import androidx.compose.ui.draw.alpha
31 | import androidx.compose.ui.graphics.Color
32 | import androidx.compose.ui.tooling.preview.Preview
33 | import androidx.compose.ui.unit.dp
34 | import androidx.compose.ui.unit.sp
35 |
36 | @Composable
37 | fun SectionSpacer(
38 | modifier: Modifier = Modifier,
39 | title:String? = null
40 | ){
41 | Box{
42 | Box(
43 | modifier = modifier
44 | .height(50.dp)
45 | .alpha(0.04f)
46 | .background(color = MaterialTheme.colorScheme.onSurface)
47 |
48 | )
49 | Column(
50 | modifier = Modifier
51 | .align(Alignment.BottomStart)
52 | .padding(bottom = 8.dp) // Adjust the padding as needed
53 | ) {
54 | title?.let {
55 | Text(
56 | modifier = Modifier.padding(start = 12.dp),
57 | text = it,
58 | style = MaterialTheme.typography.bodySmall,
59 | fontSize = 14.sp
60 | )
61 | }
62 | }
63 |
64 | }
65 |
66 | }
67 |
68 | @Preview(showBackground = true)
69 | @Composable
70 | fun PreviewSS(){
71 | SectionSpacer(modifier = Modifier.fillMaxWidth())
72 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/home/alertdialog/WaterAmountChip.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.home.alertdialog
18 |
19 | import androidx.compose.foundation.Image
20 | import androidx.compose.foundation.layout.wrapContentWidth
21 | import androidx.compose.material.icons.Icons
22 | import androidx.compose.material.icons.filled.Done
23 | import androidx.compose.material3.FilterChip
24 | import androidx.compose.material3.FilterChipDefaults
25 | import androidx.compose.material3.Icon
26 | import androidx.compose.material3.Text
27 | import androidx.compose.runtime.Composable
28 | import androidx.compose.runtime.getValue
29 | import androidx.compose.runtime.mutableStateOf
30 | import androidx.compose.runtime.remember
31 | import androidx.compose.runtime.setValue
32 | import androidx.compose.ui.Modifier
33 | import androidx.compose.ui.res.painterResource
34 | import androidx.compose.ui.res.stringResource
35 | import com.criticalay.neer.R
36 |
37 | @Composable
38 | fun WaterAmountChip(
39 | waterAmount:String
40 | ) {
41 | var selected by remember { mutableStateOf(false) }
42 |
43 | FilterChip(
44 | modifier = Modifier.wrapContentWidth(),
45 | onClick = { selected = !selected },
46 | label = {
47 | Text(
48 | maxLines = 1,
49 | text = waterAmount)
50 | },
51 | selected = selected,
52 | leadingIcon = {
53 | Image(painter = painterResource(
54 | id = R.drawable.ic_juice_glass), contentDescription = null )
55 | },
56 | trailingIcon = if (selected) {
57 | {
58 | Icon(
59 | imageVector = Icons.Filled.Done,
60 | contentDescription = stringResource(R.string.done),
61 | )
62 | }
63 | } else {
64 | null
65 | },
66 | )
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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 | package com.criticalay.neer.ui.theme
17 |
18 | import android.os.Build
19 | import androidx.compose.foundation.isSystemInDarkTheme
20 | import androidx.compose.material3.MaterialTheme
21 | import androidx.compose.material3.darkColorScheme
22 | import androidx.compose.material3.dynamicDarkColorScheme
23 | import androidx.compose.material3.dynamicLightColorScheme
24 | import androidx.compose.material3.lightColorScheme
25 | import androidx.compose.runtime.Composable
26 | import androidx.compose.ui.platform.LocalContext
27 |
28 | private val DarkColorScheme = darkColorScheme(
29 | primary = DarkBluePrimary,
30 | secondary = DarkBlueSecondary,
31 | tertiary = DarkBlueTertiary
32 | )
33 |
34 | private val LightColorScheme = lightColorScheme(
35 | primary = BluePrimary,
36 | secondary = BlueSecondary,
37 | tertiary = BlueTertiary
38 |
39 | /* Other default colors to override
40 | background = Color(0xFFFFFBFE),
41 | surface = Color(0xFFFFFBFE),
42 | onPrimary = Color.White,
43 | onSecondary = Color.White,
44 | onTertiary = Color.White,
45 | onBackground = Color(0xFF1C1B1F),
46 | onSurface = Color(0xFF1C1B1F),
47 | */
48 | )
49 |
50 | @Composable
51 | fun NeerTheme(
52 | darkTheme: Boolean = isSystemInDarkTheme(),
53 | // Dynamic color is available on Android 12+
54 | dynamicColor: Boolean = false,
55 | content: @Composable () -> Unit
56 | ) {
57 | val colorScheme = when {
58 | dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
59 | val context = LocalContext.current
60 | if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
61 | }
62 |
63 | darkTheme -> DarkColorScheme
64 | else -> LightColorScheme
65 | }
66 |
67 | MaterialTheme(
68 | colorScheme = colorScheme,
69 | typography = Typography,
70 | content = content
71 | )
72 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/dao/UserDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.dao
18 |
19 | import androidx.room.Dao
20 | import androidx.room.Insert
21 | import androidx.room.OnConflictStrategy
22 | import androidx.room.Query
23 | import androidx.room.Transaction
24 | import androidx.room.Update
25 | import com.criticalay.neer.data.model.Gender
26 | import com.criticalay.neer.data.model.Units
27 | import com.criticalay.neer.data.model.User
28 | import com.criticalay.neer.utils.Constants
29 | import kotlinx.coroutines.flow.Flow
30 | import java.time.LocalTime
31 |
32 | @Dao
33 | interface UserDao {
34 | @Query("SELECT * FROM ${Constants.USER_DATABASE_TABLE}")
35 | suspend fun getUser(): User?
36 |
37 | @Insert(onConflict = OnConflictStrategy.REPLACE)
38 | suspend fun addUser(user: User)
39 |
40 | @Update
41 | suspend fun updateUser(user: User)
42 |
43 | @Query("SELECT * FROM ${Constants.USER_DATABASE_TABLE}")
44 | fun getUserDetails() : Flow
45 |
46 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET name = :name")
47 | suspend fun updateUserName(name: String)
48 |
49 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET age = :age")
50 | suspend fun updateUserAge(age: Int)
51 |
52 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET weight = :weight")
53 | suspend fun updateUserWeight(weight: Double)
54 |
55 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET height = :height")
56 | suspend fun updateUserHeight(height: Double)
57 |
58 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET gender = :gender")
59 | suspend fun updateUserGender(gender: Gender)
60 |
61 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET bedTime = :bedTime")
62 | suspend fun updateUserSleepTime(bedTime: LocalTime)
63 |
64 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET wakeUpTime = :wakeUpTime")
65 | suspend fun updateUserWakeUpTime(wakeUpTime: LocalTime)
66 |
67 | @Query("UPDATE ${Constants.USER_DATABASE_TABLE} SET unit = :unit")
68 | suspend fun updateUserUnits(unit: Units)
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/NeerApp.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer
18 |
19 | import android.app.Application
20 | import android.app.Notification
21 | import android.app.NotificationChannel
22 | import android.app.NotificationManager
23 | import android.content.Context
24 | import android.os.Build
25 | import com.criticalay.neer.utils.Constants.CUSTOM_REMINDER_CHANNEL_ID
26 | import com.criticalay.neer.utils.Constants.WATER_REMINDER_CHANNEL_ID
27 | import dagger.hilt.android.HiltAndroidApp
28 | import timber.log.Timber
29 | import timber.log.Timber.Forest.plant
30 |
31 | @HiltAndroidApp
32 | class NeerApp:Application() {
33 | override fun onCreate() {
34 | super.onCreate()
35 | if (BuildConfig.DEBUG) {
36 | plant(Timber.DebugTree())
37 | }
38 | createNotificationChannel()
39 | createCustomNotificationChannel()
40 | }
41 |
42 | private fun createNotificationChannel() {
43 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
44 | val channel = NotificationChannel(
45 | WATER_REMINDER_CHANNEL_ID,
46 | getString(R.string.water),
47 | NotificationManager.IMPORTANCE_HIGH
48 | )
49 | channel.description = getString(R.string.notification_description)
50 | val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
51 | notificationManager.createNotificationChannel(channel)
52 |
53 | }
54 | }
55 |
56 | private fun createCustomNotificationChannel(){
57 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
58 | val channel = NotificationChannel(
59 | CUSTOM_REMINDER_CHANNEL_ID,
60 | getString(R.string.custom_reminders),
61 | NotificationManager.IMPORTANCE_HIGH
62 | )
63 | channel.description = getString(R.string.notification_description)
64 | val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
65 | notificationManager.createNotificationChannel(channel)
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
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 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/NeerDatabase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data
18 |
19 | import androidx.room.AutoMigration
20 | import androidx.room.Database
21 | import androidx.room.RoomDatabase
22 | import androidx.room.TypeConverters
23 | import androidx.room.migration.AutoMigrationSpec
24 | import androidx.room.migration.Migration
25 | import androidx.sqlite.db.SupportSQLiteDatabase
26 | import com.criticalay.neer.alarm.default_alarm.data.AlarmDao
27 | import com.criticalay.neer.alarm.default_alarm.data.AlarmItem
28 | import com.criticalay.neer.data.dao.BeverageDao
29 | import com.criticalay.neer.data.dao.IntakeDao
30 | import com.criticalay.neer.data.dao.UserDao
31 | import com.criticalay.neer.data.model.Beverage
32 | import com.criticalay.neer.data.model.Intake
33 | import com.criticalay.neer.data.model.User
34 | import com.criticalay.neer.utils.Constants.ALARM_DATABASE_TABLE
35 | import com.criticalay.neer.utils.Converters
36 |
37 | @Database(entities = [
38 | Beverage::class,
39 | User::class,
40 | Intake::class,
41 | AlarmItem::class],
42 | version = 2, exportSchema = true)
43 | @TypeConverters(Converters::class)
44 | abstract class NeerDatabase : RoomDatabase() {
45 | abstract fun userDao(): UserDao
46 | abstract fun intakeDao() : IntakeDao
47 | abstract fun beverageDao() : BeverageDao
48 | abstract fun alarmDao(): AlarmDao
49 |
50 | companion object {
51 | val MIGRATION_1_2 = object : Migration(1, 2) {
52 | override fun migrate(db: SupportSQLiteDatabase) {
53 | // Migration code goes here
54 | // Example:
55 | // database.execSQL("ALTER TABLE users ADD COLUMN age INTEGER")
56 | db.execSQL("DROP TABLE IF EXISTS $ALARM_DATABASE_TABLE")
57 |
58 | // Create the new table for AlarmItem with the corrected structure
59 | db.execSQL(
60 | "CREATE TABLE IF NOT EXISTS $ALARM_DATABASE_TABLE (" +
61 | "alarmId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
62 | "time INTEGER NOT NULL," + // Corrected to INTEGER
63 | "interval REAL," +
64 | "title TEXT NOT NULL," +
65 | "message TEXT NOT NULL," +
66 | "repeating INTEGER NOT NULL DEFAULT 0," +
67 | "alarmState INTEGER NOT NULL DEFAULT 1)"
68 | )
69 | }
70 | }
71 |
72 | }
73 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/userdetails/UnitItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.userdetails
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.offset
22 | import androidx.compose.foundation.layout.padding
23 | import androidx.compose.material3.DropdownMenu
24 | import androidx.compose.material3.DropdownMenuItem
25 | import androidx.compose.material3.Text
26 | import androidx.compose.runtime.Composable
27 | import androidx.compose.runtime.getValue
28 | import androidx.compose.runtime.mutableStateOf
29 | import androidx.compose.runtime.remember
30 | import androidx.compose.runtime.setValue
31 | import androidx.compose.ui.Alignment
32 | import androidx.compose.ui.Modifier
33 | import androidx.compose.ui.res.stringResource
34 | import androidx.compose.ui.unit.dp
35 | import androidx.compose.ui.unit.sp
36 | import com.criticalay.neer.R
37 | import com.criticalay.neer.data.model.Units
38 | import com.criticalay.neer.ui.composables.settings.SettingItem
39 |
40 | @Composable
41 | fun UnitItem(
42 | modifier: Modifier = Modifier,
43 | title: String,
44 | selectedUnit: Units,
45 | onOptionSelected: (option: Units) -> Unit
46 | ) {
47 | var expanded by remember { mutableStateOf(false) }
48 |
49 | SettingItem(modifier = modifier) {
50 | Row(
51 | modifier = Modifier
52 | .clickable(
53 | onClick = { expanded = !expanded },
54 | onClickLabel = stringResource(R.string.select_unit)
55 | )
56 | .padding(horizontal = 16.dp),
57 | verticalAlignment = Alignment.CenterVertically
58 | ) {
59 | Text(
60 | modifier = Modifier.weight(2f),
61 | fontSize = 18.sp,
62 | text = title
63 | )
64 | Text(text = selectedUnit.unitValue)
65 | }
66 | DropdownMenu(
67 | expanded = expanded,
68 | onDismissRequest = { expanded = false },
69 | ) {
70 | Units.entries.forEach { units ->
71 | DropdownMenuItem(
72 | text = { Text(text = units.unitValue) },
73 | onClick = {
74 | onOptionSelected(units)
75 | expanded = false
76 | },
77 | Modifier.offset(16.dp, 0.dp)
78 | )
79 | }
80 | }
81 | }
82 |
83 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/userdetails/GenderItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.userdetails
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.offset
22 | import androidx.compose.foundation.layout.padding
23 | import androidx.compose.material3.DropdownMenu
24 | import androidx.compose.material3.DropdownMenuItem
25 | import androidx.compose.material3.Text
26 | import androidx.compose.runtime.Composable
27 | import androidx.compose.runtime.getValue
28 | import androidx.compose.runtime.mutableStateOf
29 | import androidx.compose.runtime.remember
30 | import androidx.compose.runtime.setValue
31 | import androidx.compose.ui.Alignment
32 | import androidx.compose.ui.Modifier
33 | import androidx.compose.ui.res.stringResource
34 | import androidx.compose.ui.unit.dp
35 | import androidx.compose.ui.unit.sp
36 | import com.criticalay.neer.R
37 | import com.criticalay.neer.data.model.Gender
38 | import com.criticalay.neer.ui.composables.settings.SettingItem
39 |
40 | @Composable
41 | fun GenderItem(
42 | modifier: Modifier = Modifier,
43 | title: String,
44 | selectedGender:String,
45 | onOptionSelected: (option: Gender) -> Unit
46 | ) {
47 | var expanded by remember { mutableStateOf(false) }
48 |
49 | SettingItem(modifier = modifier) {
50 | Row(
51 | modifier = Modifier
52 | .clickable(
53 | onClick = { expanded = !expanded },
54 | onClickLabel = stringResource(R.string.select_gender)
55 | )
56 | .padding(horizontal = 16.dp),
57 | verticalAlignment = Alignment.CenterVertically
58 | ) {
59 | Text(
60 | modifier = Modifier.weight(2f),
61 | fontSize = 18.sp,
62 | text = title
63 | )
64 | Text(text = selectedGender)
65 | }
66 | DropdownMenu(
67 | expanded = expanded,
68 | onDismissRequest = { expanded = false },
69 | ) {
70 | Gender.entries.forEach { gender ->
71 | DropdownMenuItem(
72 | text = { Text(text = gender.name) },
73 | onClick = {
74 | onOptionSelected(gender)
75 | expanded = false
76 | },
77 | Modifier.offset(16.dp, 0.dp)
78 | )
79 | }
80 | }
81 | }
82 |
83 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/data/dao/IntakeDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.data.dao
18 |
19 | import androidx.room.Dao
20 | import androidx.room.Delete
21 | import androidx.room.Insert
22 | import androidx.room.Query
23 | import androidx.room.Update
24 | import com.criticalay.neer.data.model.Intake
25 | import kotlinx.coroutines.flow.Flow
26 | import java.time.LocalDateTime
27 |
28 | @Dao
29 | interface IntakeDao {
30 |
31 | // Method to insert a new water intake entry
32 | @Insert
33 | suspend fun insertIntake(intake: Intake)
34 |
35 | // Method to delete a water intake entry
36 | @Delete
37 | suspend fun deleteIntake(intake: Intake)
38 |
39 | // Method to update a water intake entry
40 | @Update
41 | suspend fun updateIntake(intake: Intake)
42 |
43 | // Method to get water intake entries for today
44 | @Query("SELECT * FROM intake WHERE beverageId = :waterBeverageId AND intakeDateTime >= :startOfDay AND intakeDateTime < :startOfNextDay ORDER BY intakeId DESC")
45 | fun getWaterIntakesForToday(waterBeverageId: Long, startOfDay: LocalDateTime, startOfNextDay: LocalDateTime): Flow>
46 |
47 |
48 | // Method to get water intake entries for a specific date range
49 | @Query("SELECT * FROM intake WHERE beverageId = :waterBeverageId AND DATE(intakeDateTime) BETWEEN DATE(:startDate) AND DATE(:endDate)")
50 | fun getWaterIntakesForDateRange(waterBeverageId: Long, startDate: LocalDateTime, endDate: LocalDateTime): Flow>
51 |
52 | // Method to get the total amount of water intake for today
53 | @Query("SELECT SUM(intakeAmount) FROM intake WHERE beverageId = :waterBeverageId AND intakeDateTime >= :startDate AND intakeDateTime < :endDate ")
54 | fun getTotalWaterIntakeForToday(waterBeverageId: Long, startDate: LocalDateTime, endDate: LocalDateTime): Flow
55 |
56 | // Method to get monthly average intake amount for a specific month
57 | @Query("SELECT AVG(intakeAmount) FROM intake WHERE beverageId = :beverageId AND strftime('%Y-%m', intakeDateTime) = :month")
58 | suspend fun getMonthlyAverageIntake(beverageId: Long, month: String): Double?
59 |
60 | // Method to get weekly average intake amount for a specific week
61 | @Query("SELECT AVG(intakeAmount) FROM intake WHERE beverageId = :beverageId AND strftime('%W', intakeDateTime) = :week")
62 | suspend fun getWeeklyAverageIntake(beverageId: Long, week: String): Double?
63 |
64 | @Query("UPDATE intake SET intakeAmount = :intakeAmount WHERE intakeId = :intakeId")
65 | suspend fun updateIntakeAmountById(intakeId: Long, intakeAmount: Int)
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/notification/NeerNotificationService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.notification
18 |
19 | import android.app.NotificationManager
20 | import android.app.PendingIntent
21 | import android.content.Context
22 | import android.content.Intent
23 | import androidx.core.app.NotificationCompat
24 | import com.criticalay.neer.NeerActivity
25 | import com.criticalay.neer.R
26 | import com.criticalay.neer.utils.Constants.CUSTOM_REMINDER_CHANNEL_ID
27 | import com.criticalay.neer.utils.Constants.WATER_REMINDER_CHANNEL_ID
28 | import com.criticalay.neer.utils.PreferencesManager
29 | import com.criticalay.neer.utils.SleepCycle
30 | import timber.log.Timber
31 | import java.time.LocalTime
32 | import java.time.ZoneId
33 | import java.time.temporal.ChronoUnit
34 |
35 | class NeerNotificationService(
36 | private val context: Context
37 | ) : NeerNotification {
38 |
39 | private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
40 |
41 | override fun showNotification(notificationItem: NotificationItem) {
42 | Timber.d("Showing notification")
43 | val activityIntent = Intent(context, NeerActivity::class.java)
44 | val activityPendingIntent = PendingIntent.getActivity(
45 | context,
46 | 1,
47 | activityIntent,
48 | PendingIntent.FLAG_IMMUTABLE
49 | )
50 | val notification = NotificationCompat.Builder(context, WATER_REMINDER_CHANNEL_ID)
51 | .setSmallIcon(R.drawable.ic_outline_water_bottle)
52 | .setContentTitle(notificationItem.title)
53 | .setContentText(notificationItem.message)
54 | .setContentIntent(activityPendingIntent)
55 | .build()
56 |
57 | notificationManager.notify(1, notification)
58 | }
59 |
60 | override fun showCustomNotification(notificationItem: NotificationItem) {
61 | Timber.d("Showing notification")
62 | val activityIntent = Intent(context, NeerActivity::class.java)
63 | val activityPendingIntent = PendingIntent.getActivity(
64 | context,
65 | 2,
66 | activityIntent,
67 | PendingIntent.FLAG_IMMUTABLE
68 | )
69 | val notification = NotificationCompat.Builder(context, CUSTOM_REMINDER_CHANNEL_ID)
70 | .setSmallIcon(R.drawable.ic_outline_water_bottle)
71 | .setContentTitle(notificationItem.title)
72 | .setContentText(notificationItem.message)
73 | .setContentIntent(activityPendingIntent)
74 | .build()
75 |
76 | notificationManager.notify(2, notification)
77 | }
78 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/notification/NotificationIntervalSetting.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.notification
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.padding
22 | import androidx.compose.material.icons.Icons
23 | import androidx.compose.material.icons.outlined.Info
24 | import androidx.compose.material.icons.outlined.Timelapse
25 | import androidx.compose.material3.Icon
26 | import androidx.compose.material3.Text
27 | import androidx.compose.runtime.Composable
28 | import androidx.compose.runtime.getValue
29 | import androidx.compose.runtime.mutableStateOf
30 | import androidx.compose.runtime.remember
31 | import androidx.compose.runtime.setValue
32 | import androidx.compose.ui.Alignment
33 | import androidx.compose.ui.Modifier
34 | import androidx.compose.ui.res.stringResource
35 | import androidx.compose.ui.semantics.semantics
36 | import androidx.compose.ui.unit.dp
37 | import androidx.compose.ui.unit.sp
38 | import com.criticalay.neer.R
39 | import com.criticalay.neer.ui.composables.notification.dialog.NotificationIntervalDialog
40 | import com.criticalay.neer.ui.composables.settings.SettingItem
41 |
42 | @Composable
43 | fun NotificationIntervalSetting(
44 | modifier: Modifier = Modifier,
45 | notificationInterval: Double,
46 | newInterval : (interval:Double) -> Unit
47 | ) {
48 | var showDialog by remember {
49 | mutableStateOf(false)
50 | }
51 | SettingItem(modifier = modifier.clickable {
52 | showDialog = true
53 | }){
54 | Row(
55 | modifier = Modifier
56 | .semantics(mergeDescendants = true) {}
57 | .padding(horizontal = 16.dp),
58 | verticalAlignment = Alignment.CenterVertically
59 | ){
60 | Icon(
61 | modifier= Modifier.padding(5.dp),
62 | imageVector = Icons.Outlined.Timelapse,
63 | contentDescription = null)
64 | Text(
65 | modifier = Modifier
66 | .weight(1f).padding(start = 5.dp),
67 | fontSize = 18.sp,
68 | text = stringResource(R.string.notification_interval)
69 | )
70 |
71 | Text(
72 | fontSize = 18.sp,
73 | text = stringResource(R.string.hrs, notificationInterval)
74 | )
75 | }
76 | }
77 | if (showDialog) {
78 | NotificationIntervalDialog(
79 | interval = notificationInterval,
80 | showAlertDialog = { show -> showDialog = show },
81 | newValue ={interval ->
82 | newInterval(interval)
83 | } )
84 | }
85 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/notification/NotificationSetting.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.notification
18 |
19 | import androidx.compose.foundation.layout.Row
20 | import androidx.compose.foundation.layout.padding
21 | import androidx.compose.foundation.selection.toggleable
22 | import androidx.compose.material.icons.Icons
23 | import androidx.compose.material.icons.outlined.Campaign
24 | import androidx.compose.material.icons.outlined.HistoryToggleOff
25 | import androidx.compose.material.icons.outlined.Info
26 | import androidx.compose.material3.Icon
27 | import androidx.compose.material3.Switch
28 | import androidx.compose.material3.Text
29 | import androidx.compose.runtime.Composable
30 | import androidx.compose.ui.Alignment
31 | import androidx.compose.ui.Modifier
32 | import androidx.compose.ui.res.stringResource
33 | import androidx.compose.ui.semantics.Role
34 | import androidx.compose.ui.semantics.semantics
35 | import androidx.compose.ui.semantics.stateDescription
36 | import androidx.compose.ui.tooling.preview.Preview
37 | import androidx.compose.ui.unit.dp
38 | import androidx.compose.ui.unit.sp
39 | import com.criticalay.neer.R
40 | import com.criticalay.neer.ui.composables.settings.SettingItem
41 |
42 | @Composable
43 | fun NotificationSetting(
44 | modifier: Modifier = Modifier,
45 | title:String,
46 | checked:Boolean,
47 | onCheckChanged: (checked:Boolean) -> Unit
48 | ){
49 | val notificationsEnabledState = if (checked) {
50 | stringResource(R.string.cd_notifications_enabled)
51 | } else stringResource(R.string.cd_notifications_disabled)
52 |
53 | SettingItem(modifier=modifier) {
54 | Row(
55 | modifier = Modifier
56 | .toggleable(
57 | value = checked,
58 | onValueChange = onCheckChanged,
59 | role = Role.Switch
60 | )
61 | .semantics {
62 | stateDescription = notificationsEnabledState
63 | }
64 | .padding(horizontal = 16.dp),
65 | verticalAlignment = Alignment.CenterVertically
66 | ) {
67 | Icon(
68 | modifier= Modifier.padding(5.dp),
69 | imageVector = Icons.Outlined.Campaign,
70 | contentDescription = null)
71 | Text(
72 | text = title,
73 | modifier = Modifier
74 | .weight(1f).padding(start = 5.dp),
75 | fontSize = 18.sp
76 | )
77 | Switch(checked = checked, onCheckedChange = null)
78 | }
79 | }
80 | }
81 |
82 | @Composable
83 | @Preview
84 | fun NotificationSettingsPreview(){
85 | NotificationSetting( title = "Enable Notification", checked = false, onCheckChanged = { })
86 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/timepicker/TimePickerDialog.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.timepicker
18 |
19 | import androidx.compose.foundation.background
20 | import androidx.compose.foundation.layout.Arrangement
21 | import androidx.compose.foundation.layout.Column
22 | import androidx.compose.foundation.layout.Row
23 | import androidx.compose.foundation.layout.fillMaxWidth
24 | import androidx.compose.foundation.layout.padding
25 | import androidx.compose.material3.BasicAlertDialog
26 | import androidx.compose.material3.ExperimentalMaterial3Api
27 | import androidx.compose.material3.MaterialTheme
28 | import androidx.compose.material3.Text
29 | import androidx.compose.material3.TextButton
30 | import androidx.compose.material3.TimePicker
31 | import androidx.compose.material3.TimePickerState
32 | import androidx.compose.runtime.Composable
33 | import androidx.compose.ui.Alignment
34 | import androidx.compose.ui.Modifier
35 | import androidx.compose.ui.graphics.Color
36 | import androidx.compose.ui.res.stringResource
37 | import androidx.compose.ui.unit.dp
38 | import com.criticalay.neer.R
39 | import java.time.LocalTime
40 |
41 | @OptIn(ExperimentalMaterial3Api::class)
42 | @Composable
43 | fun TimeDialog(
44 | showDialog: Boolean,
45 | onDismissRequest: () -> Unit,
46 | onConfirm: (time: LocalTime) -> Unit,
47 | timeState: TimePickerState,
48 | ) {
49 | if (showDialog) {
50 | BasicAlertDialog(
51 | onDismissRequest = onDismissRequest,
52 | modifier = Modifier.fillMaxWidth()
53 | ) {
54 | Column(
55 | modifier = Modifier
56 | .background(color = MaterialTheme.colorScheme.background)
57 | .padding(top = 28.dp, start = 20.dp, end = 20.dp, bottom = 12.dp),
58 | verticalArrangement = Arrangement.Center,
59 | horizontalAlignment = Alignment.CenterHorizontally
60 | ) {
61 |
62 | TimePicker(state = timeState)
63 |
64 | Row(
65 | modifier = Modifier
66 | .padding(top = 12.dp)
67 | .fillMaxWidth(),
68 | horizontalArrangement = Arrangement.End
69 | ) {
70 | TextButton(onClick = onDismissRequest) {
71 | Text(text = stringResource(id = R.string.dismiss))
72 | }
73 | TextButton(onClick = {
74 | onDismissRequest()
75 | val selectedTime = LocalTime.of(timeState.hour, timeState.minute)
76 | onConfirm(selectedTime)
77 | }) {
78 | Text(text = stringResource(id = R.string.confirm))
79 | }
80 | }
81 | }
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/default_alarm/AlarmReceiver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.default_alarm
18 |
19 | import android.content.BroadcastReceiver
20 | import android.content.Context
21 | import android.content.Intent
22 | import com.criticalay.neer.alarm.default_alarm.data.AlarmDao
23 | import com.criticalay.neer.notification.NeerNotificationService
24 | import com.criticalay.neer.notification.NotificationItem
25 | import com.criticalay.neer.utils.AppUtils
26 | import com.criticalay.neer.utils.PreferencesManager
27 | import com.criticalay.neer.utils.SleepCycle
28 | import dagger.hilt.android.AndroidEntryPoint
29 | import kotlinx.coroutines.CoroutineScope
30 | import kotlinx.coroutines.Dispatchers
31 | import kotlinx.coroutines.launch
32 | import timber.log.Timber
33 | import java.time.LocalTime
34 | import java.time.ZoneId
35 | import java.time.temporal.ChronoUnit
36 | import javax.inject.Inject
37 |
38 | @AndroidEntryPoint
39 | class AlarmReceiver:BroadcastReceiver() {
40 |
41 | @Inject
42 | lateinit var alarmDao: AlarmDao
43 |
44 | override fun onReceive(context: Context, intent: Intent?) {
45 | Timber.d("onReceive:: getting intent")
46 | if (intent != null) {
47 | val notificationType = intent.getStringExtra("NOTIFICATION_TYPE") ?: return
48 | val alarmId = intent.getLongExtra("ALARM_ID", -1L)
49 |
50 | Timber.d("Intent not null, creating notification")
51 | val notificationItem = NotificationItem(
52 | title = AppUtils.getRandomTitle(context),
53 | message = AppUtils.getRandomMessage(context)
54 | )
55 | val currentTime = LocalTime.now(ZoneId.systemDefault()).truncatedTo(ChronoUnit.MINUTES)
56 | val userSleepTime = PreferencesManager(context).getSleepCycleTime(SleepCycle.SLEEP_TIME)
57 | val userWakeTime = PreferencesManager(context).getSleepCycleTime(SleepCycle.WAKE_TIME)
58 |
59 | if (currentTime.isAfter(userSleepTime) || currentTime.isBefore(userWakeTime)) {
60 | Timber.d("Skipping notification")
61 | return
62 | }
63 |
64 | val notificationService = NeerNotificationService(context)
65 | if (notificationType=="regular"){
66 | Timber.d("Regular type notification")
67 | notificationService.showNotification(notificationItem)
68 | } else{
69 | Timber.d("Custom type notification with alarmId: %d", alarmId)
70 | if (alarmId>=0) {
71 | CoroutineScope(Dispatchers.IO).launch {
72 | Timber.d("Toggling alarm state to off")
73 | alarmDao.toggleAlarmState(alarmId, false)
74 | }
75 | }
76 | notificationService.showCustomNotification(notificationItem)
77 | }
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/userdetails/time/WakupTimePicker.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.userdetails.time
18 |
19 | import androidx.compose.foundation.background
20 | import androidx.compose.foundation.layout.Arrangement
21 | import androidx.compose.foundation.layout.Column
22 | import androidx.compose.foundation.layout.Row
23 | import androidx.compose.foundation.layout.fillMaxWidth
24 | import androidx.compose.foundation.layout.padding
25 | import androidx.compose.material3.BasicAlertDialog
26 | import androidx.compose.material3.ExperimentalMaterial3Api
27 | import androidx.compose.material3.Text
28 | import androidx.compose.material3.TextButton
29 | import androidx.compose.material3.TimePicker
30 | import androidx.compose.material3.rememberTimePickerState
31 | import androidx.compose.runtime.Composable
32 | import androidx.compose.runtime.getValue
33 | import androidx.compose.runtime.mutableIntStateOf
34 | import androidx.compose.runtime.mutableStateOf
35 | import androidx.compose.runtime.remember
36 | import androidx.compose.runtime.setValue
37 | import androidx.compose.ui.Alignment
38 | import androidx.compose.ui.Modifier
39 | import androidx.compose.ui.graphics.Color
40 | import androidx.compose.ui.res.stringResource
41 | import androidx.compose.ui.tooling.preview.Preview
42 | import androidx.compose.ui.unit.dp
43 | import com.criticalay.neer.R
44 | import com.criticalay.neer.ui.composables.timepicker.TimeDialog
45 | import com.criticalay.neer.utils.TimeUtils
46 | import java.time.LocalTime
47 |
48 | @OptIn(ExperimentalMaterial3Api::class)
49 | @Composable
50 | fun WakeUpTimePicker(
51 | onTimeSelected: (time:LocalTime) -> Unit,
52 | modifier: Modifier = Modifier
53 | ) {
54 | var showDialog by remember { mutableStateOf(false) }
55 | var timeSelected by remember { mutableStateOf(false) }
56 |
57 | val defaultSelectedTime by remember { mutableStateOf(LocalTime.of(7, 0)) }
58 | val timeState = rememberTimePickerState(
59 | initialHour = defaultSelectedTime.hour,
60 | initialMinute = defaultSelectedTime.minute
61 | )
62 | val formattedTime = remember(timeState.hour, timeState.minute) {
63 | TimeUtils.formatTime(timeState.hour, timeState.minute, timeState.hour < 12)
64 | }
65 | if (!showDialog && !timeSelected) {
66 | onTimeSelected(defaultSelectedTime)
67 | }
68 |
69 | TimeDialog(
70 | showDialog = showDialog,
71 | onDismissRequest = { showDialog = false },
72 | onConfirm = { selectedTime ->
73 | showDialog = false
74 | timeSelected=true
75 | onTimeSelected(selectedTime)
76 | },
77 | timeState = timeState
78 | )
79 |
80 | WakeUpTimeItem(
81 | title = stringResource(id = R.string.wake_up_time),
82 | setTime = formattedTime,
83 | onSettingClicked = {
84 | showDialog = true
85 | }
86 | )
87 | }
88 |
89 | @Preview(showBackground = true)
90 | @Composable
91 | fun ShowDialog(){
92 | WakeUpTimePicker(onTimeSelected = {
93 | // Do something with the selected time
94 | })
95 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/userdetails/time/SleepTimePicker.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.userdetails.time
18 |
19 | import androidx.compose.foundation.background
20 | import androidx.compose.foundation.layout.Arrangement
21 | import androidx.compose.foundation.layout.Column
22 | import androidx.compose.foundation.layout.Row
23 | import androidx.compose.foundation.layout.fillMaxWidth
24 | import androidx.compose.foundation.layout.padding
25 | import androidx.compose.material3.BasicAlertDialog
26 | import androidx.compose.material3.ExperimentalMaterial3Api
27 | import androidx.compose.material3.Text
28 | import androidx.compose.material3.TextButton
29 | import androidx.compose.material3.TimePicker
30 | import androidx.compose.material3.TimePickerState
31 | import androidx.compose.material3.rememberTimePickerState
32 | import androidx.compose.runtime.Composable
33 | import androidx.compose.runtime.getValue
34 | import androidx.compose.runtime.mutableIntStateOf
35 | import androidx.compose.runtime.mutableStateOf
36 | import androidx.compose.runtime.remember
37 | import androidx.compose.runtime.setValue
38 | import androidx.compose.ui.Alignment
39 | import androidx.compose.ui.Modifier
40 | import androidx.compose.ui.graphics.Color
41 | import androidx.compose.ui.res.stringResource
42 | import androidx.compose.ui.tooling.preview.Preview
43 | import androidx.compose.ui.unit.dp
44 | import com.criticalay.neer.R
45 | import com.criticalay.neer.ui.composables.timepicker.TimeDialog
46 | import com.criticalay.neer.utils.TimeUtils.formatTime
47 | import java.time.LocalTime
48 | import java.util.Locale
49 |
50 | @OptIn(ExperimentalMaterial3Api::class)
51 | @Composable
52 | fun SleepTimePicker(
53 | onTimeSelected: (time: LocalTime) -> Unit,
54 | modifier: Modifier = Modifier
55 | ) {
56 | var showDialog by remember { mutableStateOf(false) }
57 | var timeSelected by remember { mutableStateOf(false) }
58 |
59 | val defaultSelectedTime by remember { mutableStateOf(LocalTime.of(23, 0)) }
60 | val timeState = rememberTimePickerState(
61 | initialHour = defaultSelectedTime.hour,
62 | initialMinute = defaultSelectedTime.minute
63 | )
64 | val formattedTime = remember(timeState.hour, timeState.minute) {
65 | formatTime(timeState.hour, timeState.minute, timeState.hour < 12)
66 | }
67 | if (!showDialog && !timeSelected) {
68 | onTimeSelected(defaultSelectedTime)
69 | }
70 |
71 | TimeDialog(
72 | showDialog = showDialog,
73 | onDismissRequest = { showDialog = false },
74 | onConfirm = { selectedTime ->
75 | showDialog = false
76 | onTimeSelected(selectedTime)
77 | },
78 | timeState = timeState
79 | )
80 |
81 | SleepTimeItem(
82 | title = stringResource(id = R.string.sleep_time),
83 | setTime = formattedTime,
84 | onSettingClicked = {
85 | timeSelected=true
86 | showDialog = true
87 | }
88 | )
89 | }
90 |
91 | @Preview(showBackground = true)
92 | @Composable
93 | fun ShowSleepDialog() {
94 | SleepTimePicker(onTimeSelected = {
95 | })
96 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/settings/items/Units.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.settings.items
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Box
21 | import androidx.compose.foundation.layout.Row
22 | import androidx.compose.foundation.layout.offset
23 | import androidx.compose.foundation.layout.padding
24 | import androidx.compose.material.icons.Icons
25 | import androidx.compose.material.icons.rounded.BubbleChart
26 | import androidx.compose.material.icons.rounded.Support
27 | import androidx.compose.material3.DropdownMenu
28 | import androidx.compose.material3.DropdownMenuItem
29 | import androidx.compose.material3.Icon
30 | import androidx.compose.material3.MaterialTheme
31 | import androidx.compose.material3.Text
32 | import androidx.compose.runtime.Composable
33 | import androidx.compose.runtime.getValue
34 | import androidx.compose.runtime.mutableStateOf
35 | import androidx.compose.runtime.remember
36 | import androidx.compose.runtime.setValue
37 | import androidx.compose.ui.Alignment
38 | import androidx.compose.ui.Modifier
39 | import androidx.compose.ui.res.stringResource
40 | import androidx.compose.ui.semantics.semantics
41 | import androidx.compose.ui.unit.dp
42 | import androidx.compose.ui.unit.sp
43 | import com.criticalay.neer.R
44 | import com.criticalay.neer.data.model.Units
45 | import com.criticalay.neer.ui.composables.settings.SettingItem
46 |
47 | @Composable
48 | fun Units(
49 | modifier: Modifier = Modifier,
50 | userSelectedUnits:String,
51 | newUnits: (value:Units) -> Unit
52 | ) {
53 | Box {
54 | var expanded by remember { mutableStateOf(false) }
55 | SettingItem(modifier = modifier.clickable {
56 | expanded = true
57 | }) {
58 | Row(
59 | modifier = Modifier
60 | .semantics(mergeDescendants = true) {}
61 | .padding(horizontal = 16.dp),
62 | verticalAlignment = Alignment.CenterVertically
63 | ) {
64 | Icon(
65 | modifier = Modifier.padding(end = 5.dp),
66 | imageVector = Icons.Rounded.BubbleChart,
67 | contentDescription = null
68 | )
69 | Text(
70 | modifier = Modifier
71 | .weight(1f).padding(start = 5.dp),
72 | fontSize = 18.sp,
73 | text = stringResource(R.string.units)
74 | )
75 |
76 | Text(
77 | color = MaterialTheme.colorScheme.primary,
78 | fontSize = 18.sp,
79 | text = userSelectedUnits
80 | )
81 | }
82 | }
83 | DropdownMenu(
84 | expanded = expanded,
85 | onDismissRequest = { expanded = false },
86 | ) {
87 | for (unit in Units.entries) {
88 | DropdownMenuItem(
89 | text = { Text(text = unit.unitValue) },
90 | onClick = {
91 | newUnits(unit)
92 | expanded = false
93 | },
94 | Modifier.offset(16.dp, 0.dp)
95 | )
96 | }
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Neer - Water Reminder
2 | The Water Reminder App is a simple application designed to help users stay hydrated by reminding them to drink water regularly throughout the day.
3 | It allows users to set their daily water intake goals and track their progress towards achieving them.
4 |
5 | 
6 |
7 | Install
8 | ---------
9 |
19 |
20 | ## Features
21 | * Water Intake Reminder: Receive timely notifications reminding you to drink water regularly.
22 | * Customizable Goals: Set your daily water intake goals based on your preferences and needs.
23 | * Track Your Progress: Monitor your daily water intake and view your progress toward achieving your goals.
24 | * User-Friendly Interface: Simple and intuitive interface for easy navigation and usage.
25 |
26 | ## Reporting Issues
27 | If you encounter any issues or bugs while using the Water Reminder App, please report them by opening a new issue in the GitHub repository.
28 | Include detailed information about the issue, steps to reproduce it, and any relevant screenshots or error messages.
29 |
30 | ## Feedback and Suggestions
31 | We welcome any feedback or suggestions you may have for improving the Water Reminder App. If you have ideas for new features, enhancements,
32 | or other improvements, please feel free to share them by opening a new issue or contributing directly to the codebase.
33 |
34 | ## Contribution Guidelines
35 | Thank you for considering contributing to Neer! We welcome contributions from the community to help improve and enhance the app for all users.
36 | Please take a moment to review the following guidelines before submitting your contribution:
37 |
38 | 1. Fork the Repository: Fork the Neer repository to your GitHub account.
39 | 2. Clone the Repository: Clone your forked repository to your local machine using Git.
40 | 3. Make Changes: Implement your changes and improvements to the codebase.
41 | 4. Test Your Changes: Ensure that your changes are properly tested and do not introduce any issues.
42 | 5. Commit Your Changes: Commit your changes with a clear and descriptive commit message.
43 | 6. Push Your Changes: Push your changes to your forked repository.
44 | 7. Submit a Pull Request: Create a new pull request from your forked repository to the main Neer repository.
45 |
46 |
47 | # Privacy Policy
48 | At Neer, we take your privacy seriously. This Privacy Policy explains how we collect, use, and safeguard your personal information when you use our mobile application ("App").
49 |
50 | ## Information We Collect
51 | We do not collect any personal information from users of our App.
52 |
53 | ## How We Use Your Information
54 | Since we do not collect any personal information, we do not use your information for any purpose.
55 |
56 | ## Data Security
57 | We are committed to protecting the security of your information. While we strive to use commercially acceptable means to protect your personal information,
58 | please note that no method of transmission over the internet or method of electronic storage is 100% secure and reliable, and we cannot guarantee its absolute security.
59 |
60 | ## Changes to This Privacy Policy
61 | We may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. We will notify you of any changes by posting the new Privacy Policy on this page.
62 |
63 |
64 | ## License
65 | This project is licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
66 |
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | accompanistPermissions = "0.35.0-alpha"
3 | agp = "8.4.0-alpha13"
4 | datastorePreferences = "1.0.0"
5 | desugar_jdk_libs_nio = "2.0.4"
6 | hiltAndroid = "2.50"
7 | kotlin = "1.9.22"
8 | coreKtx = "1.12.0"
9 | junit = "4.13.2"
10 | junitVersion = "1.1.5"
11 | espressoCore = "3.5.1"
12 | lifecycleRuntimeKtx = "2.7.0"
13 | activityCompose = "1.8.2"
14 | composeBom = "2024.02.00"
15 | lifecycleViewmodelKtx = "2.7.0"
16 | roomCompiler = "2.6.1"
17 | roomKtx = "2.6.1"
18 | roomRuntime = "2.6.1"
19 | runtimeLivedata = "1.6.1"
20 | timber = "5.0.1"
21 | navigationRuntimeKtx = "2.7.7"
22 | navigationCompose = "2.7.7"
23 |
24 | [libraries]
25 | accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" }
26 | androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
27 | androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
28 | androidx-lifecycle-livedata-ktx = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycleViewmodelKtx" }
29 | androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleViewmodelKtx" }
30 | androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelKtx" }
31 | androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
32 | androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomCompiler" }
33 | androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomKtx" }
34 | androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
35 | androidx-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "runtimeLivedata" }
36 | desugar_jdk_libs_nio = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar_jdk_libs_nio" }
37 | hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
38 | hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" }
39 | junit = { group = "junit", name = "junit", version.ref = "junit" }
40 | androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
41 | androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
42 | androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
43 | androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
44 | androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
45 | androidx-ui = { group = "androidx.compose.ui", name = "ui" }
46 | androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
47 | androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
48 | androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
49 | androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
50 | androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
51 | androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
52 | material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
53 | timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
54 | androidx-navigation-runtime-ktx = { group = "androidx.navigation", name = "navigation-runtime-ktx", version.ref = "navigationRuntimeKtx" }
55 | androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
56 |
57 |
58 | [plugins]
59 | android-application = { id = "com.android.application", version.ref = "agp" }
60 | jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/notification/CustomNotificationItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.notification
18 |
19 | import androidx.compose.foundation.ExperimentalFoundationApi
20 | import androidx.compose.foundation.combinedClickable
21 | import androidx.compose.foundation.layout.Box
22 | import androidx.compose.foundation.layout.Column
23 | import androidx.compose.foundation.layout.Row
24 | import androidx.compose.foundation.layout.Spacer
25 | import androidx.compose.foundation.layout.fillMaxWidth
26 | import androidx.compose.foundation.layout.padding
27 | import androidx.compose.foundation.layout.size
28 | import androidx.compose.foundation.layout.sizeIn
29 | import androidx.compose.material3.Icon
30 | import androidx.compose.material3.OutlinedCard
31 | import androidx.compose.material3.Switch
32 | import androidx.compose.material3.Text
33 | import androidx.compose.runtime.Composable
34 | import androidx.compose.ui.Alignment
35 | import androidx.compose.ui.Modifier
36 | import androidx.compose.ui.input.pointer.pointerInteropFilter
37 | import androidx.compose.ui.res.painterResource
38 | import androidx.compose.ui.text.TextStyle
39 | import androidx.compose.ui.text.font.FontWeight
40 | import androidx.compose.ui.tooling.preview.Preview
41 | import androidx.compose.ui.unit.dp
42 | import androidx.compose.ui.unit.sp
43 | import com.criticalay.neer.R
44 |
45 | @OptIn(ExperimentalFoundationApi::class)
46 | @Composable
47 | fun CustomNotificationItem(
48 | modifier: Modifier = Modifier,
49 | checked: Boolean,
50 | onCheckChanged: (checked: Boolean) -> Unit,
51 | longClick: () -> Unit,
52 | alarmRepeatable: String,
53 | time: String
54 | ) {
55 | OutlinedCard(
56 | modifier = modifier.combinedClickable(
57 | onLongClick = {
58 | longClick()
59 | },
60 | onClick = {
61 |
62 | }
63 | )
64 | ) {
65 | Row(
66 | modifier = Modifier
67 | .padding(10.dp)
68 | .fillMaxWidth()
69 | .padding(8.dp), verticalAlignment = Alignment.CenterVertically
70 | ) {
71 | Icon(
72 | modifier = Modifier
73 | .weight(0.1f)
74 | .sizeIn(minWidth = 40.dp, minHeight = 40.dp),
75 | painter = painterResource(id = R.drawable.ic_rounded_alarm_on),
76 | contentDescription = null
77 | )
78 | Spacer(Modifier.size(16.dp))
79 | Column(
80 | modifier = Modifier
81 | .weight(0.4f)
82 | .align(Alignment.CenterVertically)
83 | ) {
84 | Text(
85 | fontSize = 20.sp,
86 | text = time,
87 | style = TextStyle(fontWeight = FontWeight(600))
88 | )
89 |
90 | Text(
91 | text = alarmRepeatable
92 | )
93 | }
94 | Spacer(Modifier.size(16.dp))
95 | Switch(checked = checked, onCheckedChange = onCheckChanged)
96 | }
97 | }
98 | }
99 |
100 | @Preview
101 | @Composable
102 | fun CustomNotificationItemPreview() {
103 | CustomNotificationItem(
104 | checked = false,
105 | time = "12:02 AM",
106 | alarmRepeatable = "Repeat",
107 | onCheckChanged = {},
108 | longClick = {}
109 | )
110 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/settings/items/BedTime.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.settings.items
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.padding
22 | import androidx.compose.material.icons.Icons
23 | import androidx.compose.material.icons.rounded.Bedtime
24 | import androidx.compose.material.icons.rounded.Support
25 | import androidx.compose.material3.ExperimentalMaterial3Api
26 | import androidx.compose.material3.Icon
27 | import androidx.compose.material3.MaterialTheme
28 | import androidx.compose.material3.Text
29 | import androidx.compose.material3.rememberTimePickerState
30 | import androidx.compose.runtime.Composable
31 | import androidx.compose.runtime.getValue
32 | import androidx.compose.runtime.mutableStateOf
33 | import androidx.compose.runtime.remember
34 | import androidx.compose.runtime.setValue
35 | import androidx.compose.ui.Alignment
36 | import androidx.compose.ui.Modifier
37 | import androidx.compose.ui.res.stringResource
38 | import androidx.compose.ui.semantics.semantics
39 | import androidx.compose.ui.unit.dp
40 | import androidx.compose.ui.unit.sp
41 | import com.criticalay.neer.R
42 | import com.criticalay.neer.ui.composables.settings.SettingItem
43 | import com.criticalay.neer.ui.composables.timepicker.TimeDialog
44 | import com.criticalay.neer.utils.TimeUtils
45 | import java.time.LocalTime
46 |
47 | @OptIn(ExperimentalMaterial3Api::class)
48 | @Composable
49 | fun BedTime(
50 | modifier: Modifier = Modifier,
51 | userBedTime:LocalTime,
52 | onTimeSelected: (time: LocalTime) -> Unit,
53 | ) {
54 | var showTimeDialog by remember {
55 | mutableStateOf(false)
56 | }
57 | val defaultSelectedTime by remember { mutableStateOf(userBedTime) }
58 | val timeState = rememberTimePickerState(
59 | initialHour = defaultSelectedTime.hour,
60 | initialMinute = defaultSelectedTime.minute
61 | )
62 |
63 | val formattedTime = remember(timeState.hour, timeState.minute) {
64 | TimeUtils.formatTime(timeState.hour, timeState.minute, timeState.hour < 12)
65 | }
66 | SettingItem(modifier = modifier .clickable {
67 | showTimeDialog = true
68 | }) {
69 | Row(
70 | modifier = Modifier
71 | .semantics(mergeDescendants = true) {}
72 | .padding(horizontal = 16.dp),
73 | verticalAlignment = Alignment.CenterVertically
74 | ) {
75 | Icon(
76 | modifier = Modifier.padding(end = 5.dp),
77 | imageVector = Icons.Rounded.Bedtime,
78 | contentDescription = null
79 | )
80 | Text(
81 | modifier = Modifier
82 | .weight(1f).padding(start = 5.dp),
83 | fontSize = 18.sp,
84 | text = stringResource(R.string.sleep_time)
85 | )
86 |
87 | Text(
88 | color = MaterialTheme.colorScheme.primary,
89 | fontSize = 18.sp,
90 | text = formattedTime
91 | )
92 | }
93 | }
94 |
95 | TimeDialog(
96 | showDialog = showTimeDialog,
97 | onDismissRequest = { showTimeDialog = false },
98 | onConfirm = { selectedTime ->
99 | showTimeDialog = false
100 | onTimeSelected(selectedTime)
101 | },
102 | timeState = timeState
103 | )
104 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/timepicker/TimePickerWithDialog.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.timepicker
18 |
19 | import androidx.compose.foundation.background
20 | import androidx.compose.foundation.layout.Arrangement
21 | import androidx.compose.foundation.layout.Column
22 | import androidx.compose.foundation.layout.Row
23 | import androidx.compose.foundation.layout.fillMaxWidth
24 | import androidx.compose.foundation.layout.padding
25 | import androidx.compose.material3.BasicAlertDialog
26 | import androidx.compose.material3.Button
27 | import androidx.compose.material3.ExperimentalMaterial3Api
28 | import androidx.compose.material3.Text
29 | import androidx.compose.material3.TextButton
30 | import androidx.compose.material3.TimePicker
31 | import androidx.compose.material3.rememberTimePickerState
32 | import androidx.compose.runtime.Composable
33 | import androidx.compose.runtime.getValue
34 | import androidx.compose.runtime.mutableIntStateOf
35 | import androidx.compose.runtime.mutableStateOf
36 | import androidx.compose.runtime.remember
37 | import androidx.compose.runtime.setValue
38 | import androidx.compose.ui.Alignment.Companion.CenterHorizontally
39 | import androidx.compose.ui.Modifier
40 | import androidx.compose.ui.graphics.Color
41 | import androidx.compose.ui.tooling.preview.Preview
42 | import androidx.compose.ui.unit.dp
43 |
44 | @OptIn(ExperimentalMaterial3Api::class)
45 | @Composable
46 | fun TimePickerWithDialog() {
47 | var selectedHour by remember { mutableIntStateOf(0) }
48 | var selectedMinute by remember { mutableIntStateOf(0) }
49 | var showDialog by remember { mutableStateOf(false) }
50 | val timeState = rememberTimePickerState(
51 | initialHour = selectedHour,
52 | initialMinute = selectedMinute
53 | )
54 |
55 | if (showDialog) {
56 | BasicAlertDialog(
57 | onDismissRequest = { showDialog = false },
58 | modifier = Modifier.fillMaxWidth()
59 | ) {
60 | Column(
61 | modifier = Modifier
62 | .background(color = Color.LightGray.copy(alpha = .3f))
63 | .padding(top = 28.dp, start = 20.dp, end = 20.dp, bottom = 12.dp),
64 | verticalArrangement = Arrangement.Center,
65 | horizontalAlignment = CenterHorizontally
66 | ) {
67 | TimePicker(state = timeState)
68 | Row(
69 | modifier = Modifier
70 | .padding(top = 12.dp)
71 | .fillMaxWidth(), horizontalArrangement = Arrangement.End
72 | ) {
73 | TextButton(onClick = { showDialog = false }) {
74 | Text(text = "Dismiss")
75 | }
76 | TextButton(onClick = {
77 | showDialog = false
78 | selectedHour = timeState.hour
79 | selectedMinute = timeState.minute
80 | }) {
81 | Text(text = "Confirm")
82 | }
83 | }
84 | }
85 | }
86 | }
87 |
88 | Column(horizontalAlignment = CenterHorizontally) {
89 | Button(onClick = { showDialog = true }) {
90 | Text(text = "Show Time Picker")
91 | }
92 | Text(text = "Time is ${timeState.hour} : ${timeState.minute}")
93 | }
94 | }
95 |
96 | @Preview(showBackground = true)
97 | @Composable
98 | fun PreviewDialog(){
99 | TimePickerWithDialog()
100 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/settings/items/WakeUpTime.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.settings.items
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Row
21 | import androidx.compose.foundation.layout.padding
22 | import androidx.compose.material.icons.Icons
23 | import androidx.compose.material.icons.rounded.Support
24 | import androidx.compose.material.icons.rounded.WbSunny
25 | import androidx.compose.material3.ExperimentalMaterial3Api
26 | import androidx.compose.material3.Icon
27 | import androidx.compose.material3.MaterialTheme
28 | import androidx.compose.material3.Text
29 | import androidx.compose.material3.rememberTimePickerState
30 | import androidx.compose.runtime.Composable
31 | import androidx.compose.runtime.getValue
32 | import androidx.compose.runtime.mutableStateOf
33 | import androidx.compose.runtime.remember
34 | import androidx.compose.runtime.setValue
35 | import androidx.compose.ui.Alignment
36 | import androidx.compose.ui.Modifier
37 | import androidx.compose.ui.res.stringResource
38 | import androidx.compose.ui.semantics.semantics
39 | import androidx.compose.ui.unit.dp
40 | import androidx.compose.ui.unit.sp
41 | import com.criticalay.neer.R
42 | import com.criticalay.neer.ui.composables.settings.SettingItem
43 | import com.criticalay.neer.ui.composables.timepicker.TimeDialog
44 | import com.criticalay.neer.ui.composables.userdetails.time.WakeUpTimePicker
45 | import com.criticalay.neer.utils.TimeUtils.formatTime
46 | import java.time.LocalTime
47 |
48 | @OptIn(ExperimentalMaterial3Api::class)
49 | @Composable
50 | fun WakeUpTime(
51 | modifier: Modifier = Modifier,
52 | userWakeTime:LocalTime,
53 | onTimeSelected: (time: LocalTime) -> Unit,
54 | ) {
55 | var showTimeDialog by remember {
56 | mutableStateOf(false)
57 | }
58 | val defaultSelectedTime by remember { mutableStateOf(userWakeTime) }
59 | val timeState = rememberTimePickerState(
60 | initialHour = defaultSelectedTime.hour,
61 | initialMinute = defaultSelectedTime.minute
62 | )
63 |
64 | val formattedTime = remember(timeState.hour, timeState.minute) {
65 | formatTime(timeState.hour, timeState.minute, timeState.hour < 12)
66 | }
67 | SettingItem(modifier = modifier .clickable {
68 | showTimeDialog = true
69 | }) {
70 | Row(
71 | modifier = Modifier
72 | .semantics(mergeDescendants = true) {}
73 | .padding(horizontal = 16.dp),
74 | verticalAlignment = Alignment.CenterVertically
75 | ) {
76 | Icon(
77 | modifier = Modifier.padding(end = 5.dp),
78 | imageVector = Icons.Rounded.WbSunny,
79 | contentDescription = null
80 | )
81 | Text(
82 | modifier = Modifier
83 | .weight(1f).padding(start = 5.dp),
84 | fontSize = 18.sp,
85 | text = stringResource(R.string.wake_up_time)
86 | )
87 |
88 | Text(
89 | color = MaterialTheme.colorScheme.primary,
90 | fontSize = 18.sp,
91 | text = formattedTime
92 | )
93 | }
94 | }
95 |
96 | TimeDialog(
97 | showDialog = showTimeDialog,
98 | onDismissRequest = { showTimeDialog = false },
99 | onConfirm = { selectedTime ->
100 | showTimeDialog = false
101 | onTimeSelected(selectedTime)
102 | },
103 | timeState = timeState
104 | )
105 |
106 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/notification/dialog/NotificationDialog.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.notification.dialog
18 |
19 | import android.Manifest
20 | import android.os.Build
21 | import androidx.annotation.RequiresApi
22 | import androidx.compose.material.icons.Icons
23 | import androidx.compose.material.icons.filled.Info
24 | import androidx.compose.material3.AlertDialog
25 | import androidx.compose.material3.Icon
26 | import androidx.compose.material3.Text
27 | import androidx.compose.material3.TextButton
28 | import androidx.compose.runtime.Composable
29 | import androidx.compose.runtime.LaunchedEffect
30 | import androidx.compose.runtime.mutableStateOf
31 | import androidx.compose.runtime.remember
32 | import androidx.compose.ui.Modifier
33 | import androidx.compose.ui.graphics.vector.ImageVector
34 | import androidx.compose.ui.res.stringResource
35 | import com.criticalay.neer.R
36 | import com.google.accompanist.permissions.ExperimentalPermissionsApi
37 | import com.google.accompanist.permissions.isGranted
38 | import com.google.accompanist.permissions.rememberPermissionState
39 | import com.google.accompanist.permissions.shouldShowRationale
40 |
41 | @RequiresApi(Build.VERSION_CODES.TIRAMISU)
42 | @OptIn(ExperimentalPermissionsApi::class)
43 | @Composable
44 | fun NotificationDialog(
45 | modifier: Modifier = Modifier,
46 | permissionGranted:(state: Boolean) -> Unit
47 | ) {
48 | val openAlertDialog = remember { mutableStateOf(true) }
49 | val permissionState = rememberPermissionState(
50 | permission = Manifest.permission.POST_NOTIFICATIONS
51 | )
52 | if (permissionState.status.isGranted){
53 | permissionGranted(true)
54 | } else if (!permissionState.status.isGranted && permissionState.status.shouldShowRationale){
55 | when {
56 | openAlertDialog.value -> {
57 | AlertDialogNotification(
58 | onDismissRequest = { openAlertDialog.value = false },
59 | onConfirmation = {
60 | openAlertDialog.value = false
61 | permissionState.launchPermissionRequest()
62 | },
63 | dialogTitle = stringResource(R.string.reminder_notification),
64 | dialogText = stringResource(R.string.notification_permission_message),
65 | icon = Icons.Default.Info
66 | )
67 | }
68 | }
69 | } else{
70 | LaunchedEffect(key1 = Unit, block = { permissionState.launchPermissionRequest() })
71 | openAlertDialog.value=true
72 | }
73 | }
74 |
75 | @Composable
76 | fun AlertDialogNotification(
77 | onDismissRequest: () -> Unit,
78 | onConfirmation: () -> Unit,
79 | dialogTitle: String,
80 | dialogText: String,
81 | icon: ImageVector,
82 | ) {
83 | AlertDialog(
84 | icon = {
85 | Icon(icon, contentDescription = null)
86 | },
87 | title = {
88 | Text(text = dialogTitle)
89 | },
90 | text = {
91 | Text(text = dialogText)
92 | },
93 | onDismissRequest = {
94 | onDismissRequest()
95 | },
96 | confirmButton = {
97 | TextButton(
98 | onClick = {
99 | onConfirmation()
100 | }
101 | ) {
102 | Text(stringResource(id = R.string.confirm))
103 | }
104 | },
105 | dismissButton = {
106 | TextButton(
107 | onClick = {
108 | onDismissRequest()
109 | }
110 | ) {
111 | Text(stringResource(id = R.string.dismiss))
112 | }
113 | }
114 | )
115 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/utils/PreferencesManager.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.utils
18 |
19 | import android.content.Context
20 | import android.content.SharedPreferences
21 | import com.criticalay.neer.data.model.Units
22 | import java.time.LocalTime
23 |
24 | class PreferencesManager(context: Context) {
25 | private val sharedPreferences: SharedPreferences =
26 | context.getSharedPreferences("NeerPrefs", Context.MODE_PRIVATE)
27 |
28 | fun saveFirstLaunchStatus(isFirstLaunch: Boolean) {
29 | val editor = sharedPreferences.edit()
30 | editor.putBoolean("firstLaunch", isFirstLaunch)
31 | editor.apply()
32 | }
33 |
34 | fun isFirstLaunch(): Boolean {
35 | return sharedPreferences.getBoolean("firstLaunch", true)
36 | }
37 |
38 | fun saveOnboarding() {
39 | val editor = sharedPreferences.edit()
40 | editor.putBoolean("onboarded", true)
41 | editor.apply()
42 | }
43 |
44 | fun isOnboarded(defaultValue:Boolean): Boolean {
45 | return sharedPreferences.getBoolean("onboarded", defaultValue)
46 | }
47 |
48 | fun saveSleepCycleTime(key: SleepCycle, localTime: LocalTime) {
49 | val editor = sharedPreferences.edit()
50 | editor.putString(key.value, localTime.toString())
51 | editor.apply()
52 | }
53 |
54 | fun getSleepCycleTime(key: SleepCycle): LocalTime {
55 | val timeString = sharedPreferences.getString(key.value, null)
56 | return if (timeString != null) {
57 | LocalTime.parse(timeString)
58 | } else {
59 | LocalTime.now()
60 | }
61 | }
62 |
63 | fun saveWaterDetails() {
64 | val editor = sharedPreferences.edit()
65 | editor.putBoolean("water_details_filled", true)
66 | editor.apply()
67 | }
68 |
69 | fun isWaterDetailsFilled(): Boolean {
70 | return sharedPreferences.getBoolean("water_details_filled", false)
71 | }
72 |
73 | fun saveUserDetails() {
74 | val editor = sharedPreferences.edit()
75 | editor.putBoolean("user_details_filled", true)
76 | editor.apply()
77 | }
78 |
79 | fun isUserDetailsFilled(): Boolean {
80 | return sharedPreferences.getBoolean("user_details_filled", false)
81 | }
82 |
83 | fun setWaterAmount(value:Int) {
84 | val editor = sharedPreferences.edit()
85 | editor.putInt("selected_water_amount", value)
86 | editor.apply()
87 | }
88 |
89 | fun getWaterAmount(): Int {
90 | return sharedPreferences.getInt("selected_water_amount", 100)
91 | }
92 |
93 | fun saveNotificationPreference(value:Boolean){
94 | val editor = sharedPreferences.edit()
95 | editor.putBoolean("notification_pref", value)
96 | editor.apply()
97 | }
98 |
99 | fun getNotificationPreference():Boolean{
100 | return sharedPreferences.getBoolean("notification_pref", false)
101 | }
102 |
103 | fun setNotificationInterval(interval:Double){
104 | val editor = sharedPreferences.edit()
105 | editor.putDouble("notification_interval", interval)
106 | editor.apply()
107 | }
108 |
109 | fun getNotificationInterval():Double{
110 | return sharedPreferences.getDouble("notification_interval",1.0)
111 | }
112 |
113 | private fun SharedPreferences.Editor.putDouble(key: String, double: Double) =
114 | putLong(key, java.lang.Double.doubleToRawLongBits(double))
115 |
116 | private fun SharedPreferences.getDouble(key: String, default: Double) =
117 | java.lang.Double.longBitsToDouble(getLong(key, java.lang.Double.doubleToRawLongBits(default)))
118 |
119 | }
120 |
121 | enum class SleepCycle(val value : String) {
122 | SLEEP_TIME("sleep_time"),
123 | WAKE_TIME("wake_time")
124 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/no_custom_alarm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Neer
4 | 千克/毫升
5 | 设置
6 | 上一页
7 | 版本
8 | 来一口
9 | 今日记录
10 | 删除
11 | 编辑
12 | 输入详情
13 | 出睡时间
14 | 入睡时间
15 | 选择出睡时间
16 | 选择入睡时间
17 | 选择单位
18 | 选择性别
19 | 性别
20 | 单位
21 | 好!
22 | 饮水量(%s)
23 | 以 %s 为单位输入
24 | 完成
25 | 关闭
26 | 更改饮水量
27 | 饮水量目标
28 | 今天没喝水
29 | 水量
30 | 编辑饮水量
31 | 取消
32 | 确认
33 | 清除
34 | 隐私策略
35 | 姓名
36 | 身高
37 | 体重
38 | 通知
39 | 编辑你的名字
40 | 水
41 | 用于发送喝水提醒
42 | 提醒通知
43 | 授予本软件通知权限帮助你轻松补充水分
44 | 是时候喝水了!
45 | 保持在这一场补水游戏中的领先!喝点水歇一会,刷新自己
46 | 喝过了
47 | 通知已启用
48 | 通知已禁用
49 | 打开通知
50 | 关闭通知会导致提醒不显示。确认吗?
51 | 关闭通知
52 | 更改身高
53 | 更改体重
54 | 隐私
55 | 尊重与透明是我们的隐私策略的体现\n我们不从用户收集任何个人信息,确保隐私处于最高地位。你拥有对于你的数据的完全控制——并且在此软件中这些数据使用严格的安全手段保护。保护你的隐私是我们的首要任务
56 | Neer隐私策略
57 | 更改饮水目标
58 | "\n "
59 | 输入每日饮水总量
60 | %s 厘米
61 | 更改通知间隔
62 | 每%s小时
63 | 通知间隔
64 | 你可以根据自身情况自定义饮水提醒间隔
65 | 来!让我们从个性化饮水提醒开始良好饮水习惯的养成。设置提醒间隔然后我们一起保持健康!
66 | 欢迎开启饮水之旅!
67 | 自定义提醒
68 | 编辑提醒
69 | 个人信息
70 | 睡眠习惯
71 | 其他
72 | 支持
73 |
74 | - 千克
75 | - 磅
76 |
77 |
78 |
79 | - 保持喝水
80 | - 水分警报
81 | - 快喝点水
82 | - 喝水时间
83 | - 保持活力
84 | - 口渴提醒
85 | - 保持水分
86 | - 给自己刷个新
87 | - 饮水歇息
88 | - 现在喝水
89 | - 水分提醒
90 | - 保持湿润
91 | - H2O警报
92 | - 饮水警报
93 | - 喝水提醒
94 | - 嗓子要干了!
95 | - 水分时间
96 | - 饮水呼唤
97 | - 现在是喝水时间
98 | - 保持清爽
99 |
100 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/alarm/default_alarm/data/NeerAlarmScheduler.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.alarm.default_alarm.data
18 |
19 | import android.app.AlarmManager
20 | import android.app.PendingIntent
21 | import android.content.Context
22 | import android.content.Intent
23 | import com.criticalay.neer.alarm.default_alarm.AlarmReceiver
24 | import com.criticalay.neer.alarm.default_alarm.AlarmScheduler
25 | import timber.log.Timber
26 | import java.time.ZoneId
27 |
28 | class NeerAlarmScheduler(
29 | val context: Context
30 | ) : AlarmScheduler {
31 |
32 | private val alarmManager = context.getSystemService(AlarmManager::class.java)
33 |
34 | override fun scheduleRegular(item: AlarmItem) {
35 | Timber.d("Scheduling alarm")
36 | val intent = Intent(context, AlarmReceiver::class.java).apply {
37 | putExtra("NOTIFICATION_TYPE", "regular")
38 | }
39 |
40 | if (item.interval != null) {
41 | Timber.d("NeerAlarmScheduler interval received is %.2f", item.interval)
42 | alarmManager.setInexactRepeating(
43 | AlarmManager.RTC_WAKEUP,
44 | item.time.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000,
45 | (item.interval * 60 * 60 * 1000).toLong(),
46 | PendingIntent.getBroadcast(
47 | context,
48 | 101,
49 | intent,
50 | PendingIntent.FLAG_IMMUTABLE
51 | )
52 | )
53 | }
54 | }
55 |
56 | override fun scheduleOneTime(item: AlarmItem) {
57 | Timber.d("Scheduling custom alarm one time repeat")
58 | val intent = Intent(context, AlarmReceiver::class.java).apply {
59 | putExtra("NOTIFICATION_TYPE", "custom")
60 | putExtra("ALARM_ID", item.alarmId)
61 | }
62 | Timber.d("alarm id recieved : %d", item.alarmId)
63 |
64 | alarmManager.set(
65 | AlarmManager.RTC_WAKEUP,
66 | item.time.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000,
67 | PendingIntent.getBroadcast(
68 | context,
69 | item.alarmId.toInt(),
70 | intent,
71 | PendingIntent.FLAG_IMMUTABLE
72 | )
73 | )
74 | }
75 |
76 | override fun scheduleRepeating(item: AlarmItem) {
77 | Timber.d("Scheduling custom alarm daily repeat")
78 | val intent = Intent(context, AlarmReceiver::class.java).apply {
79 | putExtra("NOTIFICATION_TYPE", "custom")
80 | }
81 | Timber.d("NeerAlarmScheduler interval received is %.2f", item.interval)
82 | alarmManager.setInexactRepeating(
83 | AlarmManager.RTC_WAKEUP,
84 | item.time.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000,
85 | (24 * 60 * 60 * 1000).toLong(),
86 | PendingIntent.getBroadcast(
87 | context,
88 | item.alarmId.toInt(),
89 | intent,
90 | PendingIntent.FLAG_IMMUTABLE
91 | )
92 | )
93 | }
94 |
95 | override fun cancel() {
96 | Timber.d("Cancelling alarm")
97 | alarmManager.cancel(
98 | PendingIntent.getBroadcast(
99 | context,
100 | 101,
101 | Intent(context, AlarmReceiver::class.java),
102 | PendingIntent.FLAG_IMMUTABLE
103 | )
104 | )
105 | Timber.d("Successfully cancelled alarm")
106 | }
107 |
108 | override fun cancelCustomAlarm(alarmId: Long) {
109 | Timber.d("Cancelling custom alarm")
110 | alarmManager.cancel(
111 | PendingIntent.getBroadcast(
112 | context,
113 | alarmId.toInt(),
114 | Intent(context, AlarmReceiver::class.java),
115 | PendingIntent.FLAG_IMMUTABLE
116 | )
117 | )
118 | Timber.d("Successfully cancelled custom alarm")
119 | }
120 |
121 |
122 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/settings/items/Gender.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.settings.items
18 |
19 | import androidx.compose.foundation.clickable
20 | import androidx.compose.foundation.layout.Arrangement
21 | import androidx.compose.foundation.layout.Box
22 | import androidx.compose.foundation.layout.Column
23 | import androidx.compose.foundation.layout.Row
24 | import androidx.compose.foundation.layout.fillMaxWidth
25 | import androidx.compose.foundation.layout.offset
26 | import androidx.compose.foundation.layout.padding
27 | import androidx.compose.foundation.text.KeyboardOptions
28 | import androidx.compose.material.icons.Icons
29 | import androidx.compose.material.icons.outlined.Clear
30 | import androidx.compose.material.icons.outlined.Person
31 | import androidx.compose.material.icons.rounded.Support
32 | import androidx.compose.material.icons.rounded.Wc
33 | import androidx.compose.material3.Card
34 | import androidx.compose.material3.DropdownMenu
35 | import androidx.compose.material3.DropdownMenuItem
36 | import androidx.compose.material3.Icon
37 | import androidx.compose.material3.IconButton
38 | import androidx.compose.material3.MaterialTheme
39 | import androidx.compose.material3.Text
40 | import androidx.compose.material3.TextButton
41 | import androidx.compose.runtime.Composable
42 | import androidx.compose.runtime.getValue
43 | import androidx.compose.runtime.mutableStateOf
44 | import androidx.compose.runtime.remember
45 | import androidx.compose.runtime.setValue
46 | import androidx.compose.ui.Alignment
47 | import androidx.compose.ui.Modifier
48 | import androidx.compose.ui.res.stringResource
49 | import androidx.compose.ui.semantics.semantics
50 | import androidx.compose.ui.text.input.ImeAction
51 | import androidx.compose.ui.text.input.KeyboardType
52 | import androidx.compose.ui.unit.dp
53 | import androidx.compose.ui.unit.sp
54 | import androidx.compose.ui.window.Dialog
55 | import com.criticalay.neer.R
56 | import com.criticalay.neer.data.model.Gender
57 | import com.criticalay.neer.ui.composables.settings.SettingItem
58 | import com.criticalay.neer.ui.composables.userdetails.DetailTextField
59 |
60 | @Composable
61 | fun Gender(
62 | modifier: Modifier = Modifier,
63 | userGender: String,
64 | newValue: (name: Gender) -> Unit,
65 | ) {
66 | Box {
67 | var expanded by remember { mutableStateOf(false) }
68 | SettingItem(modifier = modifier.clickable {
69 | expanded = !expanded
70 | }) {
71 | Row(
72 | modifier = Modifier
73 | .semantics(mergeDescendants = true) {}
74 | .padding(horizontal = 16.dp),
75 | verticalAlignment = Alignment.CenterVertically
76 | ) {
77 | Icon(
78 | modifier = Modifier.padding(end = 5.dp),
79 | imageVector = Icons.Rounded.Wc,
80 | contentDescription = null
81 | )
82 | Text(
83 | modifier = Modifier
84 | .padding(start = 5.dp)
85 | .weight(1f),
86 | fontSize = 18.sp,
87 | text = stringResource(R.string.gender)
88 | )
89 |
90 | Text(
91 | color = MaterialTheme.colorScheme.primary,
92 | fontSize = 18.sp,
93 | text = userGender
94 | )
95 | }
96 | }
97 | DropdownMenu(
98 | expanded = expanded,
99 | onDismissRequest = { expanded = false },
100 | ) {
101 | for (gender in Gender.entries) {
102 | DropdownMenuItem(
103 | text = { Text(text = gender.genderValue) },
104 | onClick = {
105 | newValue(gender)
106 | expanded = false
107 | },
108 | Modifier.offset(16.dp, 0.dp)
109 | )
110 | }
111 | }
112 | }
113 | }
114 |
115 |
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/home/water/WaterRecordItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.home.water
18 |
19 | import androidx.compose.foundation.layout.Row
20 | import androidx.compose.foundation.layout.Spacer
21 | import androidx.compose.foundation.layout.fillMaxWidth
22 | import androidx.compose.foundation.layout.offset
23 | import androidx.compose.foundation.layout.padding
24 | import androidx.compose.foundation.layout.size
25 | import androidx.compose.foundation.layout.sizeIn
26 | import androidx.compose.material.icons.Icons
27 | import androidx.compose.material.icons.filled.MoreVert
28 | import androidx.compose.material3.Card
29 | import androidx.compose.material3.DropdownMenu
30 | import androidx.compose.material3.DropdownMenuItem
31 | import androidx.compose.material3.Icon
32 | import androidx.compose.material3.IconButton
33 | import androidx.compose.material3.Text
34 | import androidx.compose.runtime.Composable
35 | import androidx.compose.runtime.getValue
36 | import androidx.compose.runtime.mutableStateOf
37 | import androidx.compose.runtime.remember
38 | import androidx.compose.runtime.setValue
39 | import androidx.compose.ui.Alignment
40 | import androidx.compose.ui.Modifier
41 | import androidx.compose.ui.res.painterResource
42 | import androidx.compose.ui.tooling.preview.Preview
43 | import androidx.compose.ui.unit.dp
44 | import androidx.compose.ui.unit.sp
45 | import com.criticalay.neer.R
46 | import androidx.compose.foundation.layout.Box
47 | import androidx.compose.material3.OutlinedCard
48 | import androidx.compose.ui.res.stringResource
49 |
50 | @Composable
51 | fun WaterRecordItem(
52 | modifier: Modifier = Modifier,
53 | handleDelete: () -> Unit,
54 | handleEdit: () -> Unit,
55 | waterIntakeTime: String,
56 | waterIntakeAmount: String
57 | ) {
58 | var expanded by remember { mutableStateOf(false) }
59 | OutlinedCard {
60 | Row(modifier = modifier
61 | .fillMaxWidth()
62 | .padding(8.dp), verticalAlignment = Alignment.CenterVertically) {
63 | Icon(
64 | modifier = Modifier
65 | .weight(0.2f)
66 | .sizeIn(minWidth = 30.dp, minHeight = 30.dp),
67 | painter = painterResource(id = R.drawable.ic_outline_water_bottle),
68 | contentDescription = null
69 | )
70 | Spacer(Modifier.size(16.dp))
71 | Text(
72 | modifier = Modifier.weight(0.4f),
73 | fontSize = 20.sp,
74 | text = waterIntakeAmount
75 | )
76 | Spacer(Modifier.size(16.dp))
77 | Text(
78 | modifier = Modifier.weight(0.4f),
79 | fontSize = 20.sp,
80 | text = waterIntakeTime
81 | )
82 |
83 | // Wrap the IconButton and DropdownMenu in a Box
84 | Box {
85 | IconButton(onClick = { expanded = !expanded }) {
86 | Icon(imageVector = Icons.Default.MoreVert, contentDescription = null)
87 | }
88 |
89 | DropdownMenu(
90 | expanded = expanded,
91 | onDismissRequest = { expanded = false },
92 | modifier = Modifier.align(Alignment.TopEnd) // Position the DropdownMenu at the top end
93 | ) {
94 | DropdownMenuItem(text = { Text(text = stringResource(R.string.edit)) },
95 | onClick = {
96 | handleEdit()
97 | expanded = false
98 | },
99 | Modifier.offset(16.dp, 0.dp)
100 | )
101 | DropdownMenuItem(text = { Text(text = stringResource(R.string.delete)) },
102 | onClick = {
103 | handleDelete()
104 | expanded = false
105 | },
106 | Modifier.offset(16.dp, 0.dp)
107 | )
108 |
109 | }
110 | }
111 | }
112 | }
113 | Spacer(Modifier.size(10.dp))
114 | }
115 |
116 | @Preview(showBackground = true)
117 | @Composable
118 | fun PreviewWaterRecordItem(){
119 | WaterRecordItem(waterIntakeAmount = "300ml", waterIntakeTime = "12:53 AM", handleDelete = {}, handleEdit = {})
120 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/criticalay/neer/ui/composables/privacy/PrivacyScreen.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2024 Ashish Yadav
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.criticalay.neer.ui.composables.privacy
18 |
19 | import androidx.compose.foundation.layout.Column
20 | import androidx.compose.foundation.layout.fillMaxSize
21 | import androidx.compose.foundation.layout.padding
22 | import androidx.compose.foundation.layout.sizeIn
23 | import androidx.compose.foundation.rememberScrollState
24 | import androidx.compose.foundation.verticalScroll
25 | import androidx.compose.material.icons.Icons
26 | import androidx.compose.material.icons.automirrored.filled.ArrowBack
27 | import androidx.compose.material.icons.rounded.PrivacyTip
28 | import androidx.compose.material.icons.rounded.WaterDrop
29 | import androidx.compose.material3.CardDefaults
30 | import androidx.compose.material3.ExperimentalMaterial3Api
31 | import androidx.compose.material3.HorizontalDivider
32 | import androidx.compose.material3.Icon
33 | import androidx.compose.material3.IconButton
34 | import androidx.compose.material3.MediumTopAppBar
35 | import androidx.compose.material3.OutlinedCard
36 | import androidx.compose.material3.Scaffold
37 | import androidx.compose.material3.Text
38 | import androidx.compose.material3.TopAppBar
39 | import androidx.compose.material3.TopAppBarDefaults
40 | import androidx.compose.material3.rememberTopAppBarState
41 | import androidx.compose.runtime.Composable
42 | import androidx.compose.ui.Alignment
43 | import androidx.compose.ui.Modifier
44 | import androidx.compose.ui.input.nestedscroll.nestedScroll
45 | import androidx.compose.ui.platform.LocalContext
46 | import androidx.compose.ui.res.stringResource
47 | import androidx.compose.ui.text.style.TextAlign
48 | import androidx.compose.ui.tooling.preview.Preview
49 | import androidx.compose.ui.unit.dp
50 | import androidx.compose.ui.unit.sp
51 | import com.criticalay.neer.R
52 |
53 | @OptIn(ExperimentalMaterial3Api::class)
54 | @Composable
55 | fun PrivacyScreen(
56 | modifier: Modifier = Modifier,
57 | onBack: () -> Unit
58 | ) {
59 | val context = LocalContext.current
60 | val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
61 | Scaffold(
62 | modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
63 | topBar = {
64 | TopAppBar(
65 | title = {
66 | Text(
67 | text = stringResource(R.string.privacy),
68 | modifier = Modifier.padding(start = 10.dp)
69 | )
70 | },
71 | navigationIcon = {
72 | IconButton(onClick = { onBack() }) {
73 | Icon(
74 | imageVector = Icons.AutoMirrored.Filled.ArrowBack,
75 | contentDescription = stringResource(R.string.go_back)
76 | )
77 |
78 | }
79 | },
80 | scrollBehavior = scrollBehavior
81 | )
82 | }
83 | ) { padding ->
84 | Column(modifier = Modifier
85 | .padding(horizontal = 10.dp, vertical = padding.calculateTopPadding())
86 | .fillMaxSize()
87 | .verticalScroll(
88 | rememberScrollState()
89 | )) {
90 | OutlinedCard(
91 | modifier = Modifier
92 | .align(alignment = Alignment.CenterHorizontally)
93 | .padding(8.dp),
94 | elevation = CardDefaults.cardElevation(
95 | defaultElevation = 6.dp
96 | )
97 | ) {
98 | Icon(
99 | modifier = Modifier.sizeIn(150.dp, 150.dp),
100 | imageVector = Icons.Rounded.PrivacyTip, contentDescription = null,
101 | )
102 | }
103 | Text(
104 | modifier = Modifier.padding(top = 16.dp).align(Alignment.CenterHorizontally),
105 | text = stringResource(R.string.app_privacy_policy),
106 | fontSize = 20.sp
107 | )
108 |
109 | Text(
110 | modifier = Modifier.padding(top = 8.dp),
111 | fontSize = 14.sp,
112 | text = stringResource(R.string.privacy_policy_message)
113 | )
114 |
115 | }
116 | }
117 | }
118 |
119 | @Preview(showBackground = true)
120 | @Composable
121 | fun PreviewPrivacy(){
122 | PrivacyScreen {
123 |
124 | }
125 | }
--------------------------------------------------------------------------------