Commit 312d5b33 authored by Bandaranayake V.R.W's avatar Bandaranayake V.R.W

Update ML - Model Training/.kaggle/kaggle.json, ML - Model...

Update ML - Model Training/.kaggle/kaggle.json, ML - Model Training/Api/_pycache/main.cpython-311.pyc, ML - Model Training/Api/requirements.txt, ML - Model Training/Api/main.py, ML - Model Training/Api/Models/Model_1.tc, ML - Model Training/Api/Models/Model_1_Linear.pkl, ML - Model Training/Api/Models/Model_accuracy_98.52.tc, ML - Model Training/Api/Models/model.onnx, ML - Model Training/Api/Services/_pycache/chat.cpython-39.pyc, ML - Model Training/Api/Services/_pycache/med_rec.cpython-39.pyc, ML - Model Training/Api/Services/_pycache/chat.cpython-311.pyc, ML - Model Training/Api/Services/_pycache/eacyocr.cpython-39.pyc, ML - Model Training/Api/Services/_pycache/eacyocr.cpython-311.pyc, ML - Model Training/Api/Services/_pycache/med_rec.cpython-311.pyc, ML - Model Training/Api/Services/_pycache/recomender.cpython-39.pyc, ML - Model Training/Api/Services/_pycache/recomender.cpython-311.pyc, ML - Model Training/Api/Services/recomender.py, ML - Model Training/Api/Services/chat.py, ML - Model Training/Api/Services/eacyocr.py, ML - Model Training/Api/Services/med_rec.py, ML - Model Training/Chat/hairchat_train.ipynb, ML - Model Training/Chat/Readme.md, ML - Model Training/Chat/hairchat_chatbot.py, ML - Model Training/Chat/hairchat_chatbot.ipynb, ML - Model Training/Chat/updated_data_with_all_medication_info.json, ML - Model Training/EasyOCR/prescription_1.png, ML - Model Training/EasyOCR/easyOCR.ipynb, ML - Model Training/EasyOCR/prescription (1).jpg, ML - Model Training/EasyOCR/finalized/easyOCR.ipynb, ML - Model Training/EasyOCR/finalized/prescription (1) (1).png, ML - Model Training/EasyOCR/finalized/OCR_finalized.ipynb, ML - Model Training/EasyOCR/prescription/prescription (1)- compressed.jpg, ML - Model Training/EasyOCR/prescription/prescription (38).jpg, ML - Model Training/EasyOCR/prescription/prescription (42).jpg, ML - Model Training/EasyOCR/prescription/prescription (1).jpg, ML - Model Training/EasyOCR/prescription/prescription (2).jpg, ML - Model Training/EasyOCR/prescription/prescription (3).jpg, ML - Model Training/EasyOCR/prescription/prescription (4).jpg, ML - Model Training/EasyOCR/prescription/prescription (5).jpg, ML - Model Training/EasyOCR/prescription/prescription (6).jpg, ML - Model Training/EasyOCR/prescription/prescription (7).jpg, ML - Model Training/EasyOCR/prescription/prescription (8).jpg, ML - Model Training/EasyOCR/prescription/prescription (10).jpg, ML - Model Training/EasyOCR/prescription/prescription (9).jpg, ML - Model Training/EasyOCR/prescription/prescription (11).jpg, ML - Model Training/EasyOCR/prescription/prescription (12).jpg, ML - Model Training/EasyOCR/prescription/prescription (13).jpg, ML - Model Training/EasyOCR/prescription/prescription (14).jpg, ML - Model Training/EasyOCR/prescription/prescription (15).jpg, ML - Model Training/EasyOCR/prescription/prescription (16).jpg, ML - Model Training/EasyOCR/prescription/prescription (17).jpg, ML - Model Training/EasyOCR/prescription/prescription (18).jpg, ML - Model Training/EasyOCR/prescription/prescription (19).jpg, ML - Model Training/EasyOCR/prescription/prescription (20).jpg, ML - Model Training/EasyOCR/prescription/prescription (23).jpg, ML - Model Training/EasyOCR/prescription/prescription (21).jpg, ML - Model Training/EasyOCR/prescription/prescription (22).jpg, ML - Model Training/EasyOCR/prescription/prescription (24).jpg, ML - Model Training/EasyOCR/prescription/prescription (25).jpg, ML - Model Training/EasyOCR/prescription/prescription (26).jpg, ML - Model Training/EasyOCR/prescription/prescription (27).jpg, ML - Model Training/EasyOCR/prescription/prescription (29).jpg, ML - Model Training/EasyOCR/prescription/prescription (28).jpg, ML - Model Training/EasyOCR/prescription/prescription (31).jpg, ML - Model Training/EasyOCR/prescription/prescription (32).jpg, ML - Model Training/EasyOCR/prescription/prescription (30).jpg, ML - Model Training/EasyOCR/prescription/prescription (33).jpg, ML - Model Training/EasyOCR/prescription/prescription (34).jpg, ML - Model Training/EasyOCR/prescription/prescription (35).jpg, ML - Model Training/EasyOCR/prescription/prescription (36).jpg, ML - Model Training/EasyOCR/prescription/prescription (37).jpg, ML - Model Training/EasyOCR/prescription/prescription (39).jpg, ML - Model Training/EasyOCR/prescription/prescription (41).jpg, ML - Model Training/EasyOCR/prescription/prescription (44).jpg, ML - Model Training/EasyOCR/prescription/prescription (45).jpg, ML - Model Training/EasyOCR/prescription/prescription (43).jpg, ML - Model Training/EasyOCR/prescription/prescription (46).jpg, ML - Model Training/EasyOCR/prescription/prescription (47).jpg, ML - Model Training/EasyOCR/prescription/prescription (48).jpg, ML - Model Training/EasyOCR/prescription/prescription (50).jpg, ML - Model Training/EasyOCR/prescription/prescription (49).jpg, ML - Model Training/EasyOCR/prescription/prescription (40).jpg, ML - Model Training/EasyOCR/prescription/prescription (1).png, ML - Model Training/EasyOCR/prescription/prescription (1)- compressed.png, ML - Model Training/Recommendation/Model_1.tc, ML - Model Training/Recommendation/Recommendation_model.ipynb, App/.gradle/8.0/checksums/checksums.lock, App/.gradle/8.0/dependencies-accessors/dependencies-accessors.lock, App/.gradle/8.0/dependencies-accessors/gc.properties, App/.gradle/8.0/executionHistory/executionHistory.lock, App/.gradle/8.0/fileChanges/last-build.bin, App/.gradle/8.0/fileHashes/fileHashes.lock, App/.gradle/8.0/fileHashes/fileHashes.bin, App/.gradle/8.0/gc.properties, App/.gradle/buildOutputCleanup/buildOutputCleanup.lock, App/.gradle/buildOutputCleanup/cache.properties, App/.gradle/vcs-1/gc.properties, App/.idea/.gitignore, App/.idea/.name, App/.idea/androidTestResultsUserPreferences.xml, App/.idea/compiler.xml, App/.idea/misc.xml, App/.idea/gradle.xml, App/.idea/vcs.xml, App/.idea/workspace.xml, App/gradle/wrapper/gradle-wrapper.properties, App/gradle/wrapper/gradle-wrapper.jar, App/.gitignore, App/build.gradle, App/gradlew, App/gradle.properties, App/local.properties, App/gradlew.bat, App/settings.gradle, App/app/.gitignore, App/app/build.gradle, App/app/proguard-rules.pro, App/app/google-services.json, App/app/src/androidTest/java/com/HairDiary/ExampleInstrumentedTest.java, App/app/src/test/java/com/HairDiary/ExampleUnitTest.java, App/app/src/test/java/com/HairDiary/UserCalculationTest.java, App/app/src/main/AndroidManifest.xml, App/app/src/main/java/com/HairDiary/adapters/ChatAdapter.java, App/app/src/main/java/com/HairDiary/adapters/ReportAdapter.java, App/app/src/main/java/com/HairDiary/adapters/ScheduleAdapter.java, App/app/src/main/java/com/HairDiary/adapters/ScheduleEditAdapter.java, App/app/src/main/java/com/HairDiary/adapters/SelectProfileAdapter.java, App/app/src/main/java/com/HairDiary/adapters/TreatmentRecordsAdapter.java, App/app/src/main/java/com/HairDiary/firebase/NotificationMessagingService.java, App/app/src/main/java/com/HairDiary/firebase/RealtimeDatabase.java, App/app/src/main/java/com/HairDiary/firebase/FirestoreDatabase.java, App/app/src/main/java/com/HairDiary/models/ChatMessage.java, App/app/src/main/java/com/HairDiary/models/Device.java, App/app/src/main/java/com/HairDiary/models/ReportModel.java, App/app/src/main/java/com/HairDiary/models/User.java, App/app/src/main/java/com/HairDiary/models/ScheduledItems.java, App/app/src/main/java/com/HairDiary/models/TreatmentRecord.java, App/app/src/main/java/com/HairDiary/models/Response/ChatResponse.java, App/app/src/main/java/com/HairDiary/models/Response/ReportResponse.java, App/app/src/main/java/com/HairDiary/models/Response/TreatmentResponse.java, App/app/src/main/java/com/HairDiary/ui/activities/TreatmentRecordsActivity.java, App/app/src/main/java/com/HairDiary/ui/activities/MainActivity.java, App/app/src/main/java/com/HairDiary/ui/activities/SignInActivity.java, App/app/src/main/java/com/HairDiary/ui/activities/SignupActivity.java, App/app/src/main/java/com/HairDiary/ui/activities/ReportCameraActivity.java, App/app/src/main/java/com/HairDiary/ui/activities/UserProfileActivity.java, App/app/src/main/java/com/HairDiary/ui/fragments/DeviceFragment.java, App/app/src/main/java/com/HairDiary/ui/fragments/ChatFragment.java, App/app/src/main/java/com/HairDiary/ui/fragments/HomeFragment.java, App/app/src/main/java/com/HairDiary/ui/fragments/ReportFragment.java, App/app/src/main/java/com/HairDiary/ui/fragments/TreatmentFragment.java, App/app/src/main/java/com/HairDiary/ui/fragments/SingleReportFragment.java, App/app/src/main/java/com/HairDiary/ui/fragments/UserFragment.java, App/app/src/main/java/com/HairDiary/utilities/Constants.java, App/app/src/main/java/com/HairDiary/utilities/ImageUtilities.java, App/app/src/main/java/com/HairDiary/utilities/formatConverter.java, App/app/src/main/java/com/HairDiary/utilities/NotificationHandler.java, App/app/src/main/java/com/HairDiary/utilities/UserCalculation.java, App/app/src/main/java/com/HairDiary/utilities/PreferenceManager.java, App/app/src/main/res/drawable/account.png, App/app/src/main/res/drawable/add.png, App/app/src/main/res/drawable/calendar_img.png, App/app/src/main/res/drawable/cap_icon.png, App/app/src/main/res/drawable/chat_icon.png, App/app/src/main/res/drawable/chat_bot_white.png, App/app/src/main/res/drawable/chatbot.png, App/app/src/main/res/drawable/docs_icon.png, App/app/src/main/res/drawable/home_icon.png, App/app/src/main/res/drawable/img_ap.png, App/app/src/main/res/drawable/option.png, App/app/src/main/res/drawable/pp.jpg, App/app/src/main/res/drawable/profile_user.png, App/app/src/main/res/drawable/righticon.png, App/app/src/main/res/drawable/signout_icon.png, App/app/src/main/res/drawable/telephone.png, App/app/src/main/res/drawable/three_dot.png, App/app/src/main/res/drawable/trash_bin.png, App/app/src/main/res/drawable/treatment_icon.png, App/app/src/main/res/drawable/treatment_image.jpg, App/app/src/main/res/drawable/user_icon.png, App/app/src/main/res/drawable/background_image.xml, App/app/src/main/res/drawable/bg_add.xml, App/app/src/main/res/drawable/bg_attach_btn.xml, App/app/src/main/res/drawable/bg_btn.xml, App/app/src/main/res/drawable/bg_camera.xml, App/app/src/main/res/drawable/bg_content_top.xml, App/app/src/main/res/drawable/bg_icon.xml, App/app/src/main/res/drawable/bg_input.xml, App/app/src/main/res/drawable/bg_rec.xml, App/app/src/main/res/drawable/bg_recieved_msg.xml, App/app/src/main/res/drawable/bg_sign_in_top.xml, App/app/src/main/res/drawable/bg_sent_msg.xml, App/app/src/main/res/drawable/black_round.xml, App/app/src/main/res/drawable/bg_rectangle.xml, App/app/src/main/res/drawable/btn_add.xml, App/app/src/main/res/drawable/chat_input.xml, App/app/src/main/res/drawable/ellipse_14.xml, App/app/src/main/res/drawable/ellipse_15.xml, App/app/src/main/res/drawable/ellipse_16.xml, App/app/src/main/res/drawable/ellipse_21.xml, App/app/src/main/res/drawable/ic_add.xml, App/app/src/main/res/drawable/ic__back.xml, App/app/src/main/res/drawable/ic_add_circle.xml, App/app/src/main/res/drawable/ic_arrow_right.xml, App/app/src/main/res/drawable/ic_attach.xml, App/app/src/main/res/drawable/ic_image.xml, App/app/src/main/res/drawable/ic_info.xml, App/app/src/main/res/drawable/ic_launcher_background.xml, App/app/src/main/res/drawable/ic_send.xml, App/app/src/main/res/drawable/item_active.xml, App/app/src/main/res/drawable/line.xml, App/app/src/main/res/drawable/rec_shape.xml, App/app/src/main/res/drawable/rectangle_1.xml, App/app/src/main/res/drawable/rectangle_2.xml, App/app/src/main/res/drawable/rectangle_3.xml, App/app/src/main/res/drawable/rectangle_4.xml, App/app/src/main/res/drawable/track.xml, App/app/src/main/res/drawable/thumb.xml, App/app/src/main/res/drawable/white_box.xml, App/app/src/main/res/drawable-v24/ic_launcher_foreground.xml, App/app/src/main/res/layout/activity_main.xml, App/app/src/main/res/layout/activity_report_camera.xml, App/app/src/main/res/layout/activity_sign_in.xml, App/app/src/main/res/layout/activity_signup.xml, App/app/src/main/res/layout/activity_treatment_records.xml, App/app/src/main/res/layout/calender_dialog.xml, App/app/src/main/res/layout/activity_user_profile.xml, App/app/src/main/res/layout/chat_information_dialog.xml, App/app/src/main/res/layout/dialog_camera.xml, App/app/src/main/res/layout/fragment_chat.xml, App/app/src/main/res/layout/dialog_forget.xml, App/app/src/main/res/layout/fragment_device_new.xml, App/app/src/main/res/layout/fragment_home_new.xml, App/app/src/main/res/layout/fragment_single_report.xml, App/app/src/main/res/layout/fragment_report_new.xml, App/app/src/main/res/layout/medical_treatment.xml, App/app/src/main/res/layout/item_container_send_msg.xml, App/app/src/main/res/layout/recommend_treatment.xml, App/app/src/main/res/layout/item_treatment_record.xml, App/app/src/main/res/layout/fragment_treatment.xml, App/app/src/main/res/layout/profile_layout.xml, App/app/src/main/res/layout/schedule_item.xml, App/app/src/main/res/layout/send_image_dialog.xml, App/app/src/main/res/layout/schedule_edit_item.xml, App/app/src/main/res/layout/select_user_dialog.xml, App/app/src/main/res/layout/report_item.xml, App/app/src/main/res/layout/fragment_user.xml, App/app/src/main/res/layout/item_container_recieved_message.xml, App/app/src/main/res/layout/medical_information.xml, App/app/src/main/res/menu/menu_chat.xml, App/app/src/main/res/menu/menu_home.xml, App/app/src/main/res/menu/menu_report.xml, App/app/src/main/res/menu/menu_treatment.xml, App/app/src/main/res/menu/menu_item.xml, App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml, App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml, App/app/src/main/res/mipmap-hdpi/ic_launcher.webp, App/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp, App/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp, App/app/src/main/res/mipmap-mdpi/ic_launcher.webp, App/app/src/main/res/mipmap-xhdpi/ic_launcher.webp, App/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp, App/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp, App/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp, App/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp, App/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp, App/app/src/main/res/values/styles.xml, App/app/src/main/res/values/themes.xml, App/app/src/main/res/values/colors.xml, App/app/src/main/res/values/strings.xml, App/app/src/main/res/values-night/themes.xml, App/app/src/main/res/xml/backup_rules.xml, App/app/src/main/res/xml/data_extraction_rules.xml, App/app/src/main/res/xml/file_paths.xml files
Deleted Chat_ML/.gitkeep, Chat_ML/hairchat_chatbot.ipynb, Chat_ML/hairchat_chatbot.py, Chat_ML/hairchat_train.ipynb, Chat_ML/updated_data_with_all_medication_info.json, chat.py, hairchat_chatbot.ipynb, App/.gitkeep, README.md files
parent f12ef4f9
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
#Thu Nov 09 20:32:10 IST 2023
gradle.version=8.0
# Default ignored files
/shelf/
/workspace.xml
HairDiary
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidTestResultsUserPreferences">
<option name="androidTestResultsTableState">
<map>
<entry key="1170157800">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Tests" value="360" />
<entry key="samsung SM-G975F" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
</map>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidLayouts">
<shared>
<config />
</shared>
</component>
<component name="AutoImportSettings">
<option name="autoReloadType" value="NONE" />
</component>
<component name="ChangeListManager">
<list default="true" id="be3dc1e1-7f20-4865-9223-6484f05ab852" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="device_and_snapshot_combo_box_target[C:\Users\Ravidu\.android\avd\Pixel_5_API_34.avd]" />
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectId" id="2XwZR7PgXS6vtYo2Sx6mFiznUkZ" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;cidr.known.project.marker&quot;: &quot;true&quot;
}
}</component>
<component name="RunManager">
<configuration name="app" type="AndroidRunConfigurationType" factoryName="Android App">
<module name="HairDiary.app.main" />
<option name="DEPLOY" value="true" />
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
<option name="DEPLOY_AS_INSTANT" value="false" />
<option name="ARTIFACT_NAME" value="" />
<option name="PM_INSTALL_OPTIONS" value="" />
<option name="ALL_USERS" value="false" />
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
<option name="CLEAR_APP_STORAGE" value="false" />
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
<option name="MODE" value="default_activity" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
<option name="INSPECTION_WITHOUT_ACTIVITY_RESTART" value="false" />
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
<option name="DEBUGGER_TYPE" value="Auto" />
<Auto>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Auto>
<Hybrid>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Hybrid>
<Java>
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Java>
<Native>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Native>
<Profilers>
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
<option name="STARTUP_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
</Profilers>
<option name="DEEP_LINK" value="" />
<option name="ACTIVITY_CLASS" value="" />
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="be3dc1e1-7f20-4865-9223-6484f05ab852" name="Changes" comment="" />
<created>1699542093867</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1699542093867</updated>
</task>
<servers />
</component>
</project>
\ No newline at end of file
/build
\ No newline at end of file
plugins {
id 'com.android.application'
id 'com.google.gms.google-services'
}
android {
namespace 'com.HairDiary'
compileSdk 33
defaultConfig {
applicationId "com.HairDiary"
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures{
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.google.firebase:firebase-database:20.2.2'
implementation 'com.google.firebase:firebase-storage:20.2.1'
//test Implementation
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
testImplementation 'com.google.truth:truth:1.0.1'
androidTestImplementation 'com.google.truth:truth:1.0.1'
implementation 'com.etebarian:meow-bottom-navigation:1.2.0'
implementation 'com.google.android.gms:play-services-auth:20.6.0'
//Library for Image picker
implementation 'com.github.dhaval2404:imagepicker:2.1'
//Library Glide
implementation 'com.github.bumptech.glide:glide:4.15.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
//Scalable Size Unit (support for different screen size)
implementation 'com.intuit.sdp:sdp-android:1.1.0'
implementation 'com.intuit.ssp:ssp-android:1.1.0'
//Rounded Image View
implementation 'com.makeramen:roundedimageview:2.3.0'
//MultiDex
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'com.android.volley:volley:1.2.1'
implementation 'io.github.chaosleung:pinview:1.4.4'
//Firebase
implementation 'com.google.firebase:firebase-auth-ktx:22.0.0'
implementation 'com.google.firebase:firebase-database-ktx:20.2.1'
implementation 'com.google.firebase:firebase-firestore-ktx:24.6.0'
implementation 'com.google.firebase:firebase-messaging:23.1.2'
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:32.0.0')
// Add the dependency for the Firebase Authentication library
implementation 'com.google.firebase:firebase-auth'
// Also add the dependency for the Google Play services library and specify its version
implementation 'com.google.android.gms:play-services-auth:20.5.0'
//okhttp3 dependencies
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11'
//Gson dependency
implementation 'com.google.code.gson:gson:2.9.0'
}
\ No newline at end of file
{
"project_info": {
"project_number": "85465076249",
"firebase_url": "https://hairdiary-74048-default-rtdb.firebaseio.com",
"project_id": "hairdiary-74048",
"storage_bucket": "hairdiary-74048.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:85465076249:android:9c0441f861213ec10c1088",
"android_client_info": {
"package_name": "com.silverline.it.myapplication"
}
},
"oauth_client": [
{
"client_id": "85465076249-tj7itmno4hdtqkfgvq0pu5n13nnfub1g.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.myapplication",
"certificate_hash": "3d90f0de073e6943ba8ce37e513bc64378481333"
}
},
{
"client_id": "85465076249-jo3k800og0ita42nl8oqllpaae9kmb5r.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCJXHtllk_L-EI-5DtF_Boff1pKRhekBvk"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "85465076249-jo3k800og0ita42nl8oqllpaae9kmb5r.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:85465076249:android:9d626bb1679d00860c1088",
"android_client_info": {
"package_name": "com.HairDiary"
}
},
"oauth_client": [
{
"client_id": "85465076249-jo3k800og0ita42nl8oqllpaae9kmb5r.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCJXHtllk_L-EI-5DtF_Boff1pKRhekBvk"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "85465076249-jo3k800og0ita42nl8oqllpaae9kmb5r.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package com.HairDiary;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.HairDiary", appContext.getPackageName());
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<permission
android:name="com.HairDiary.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.HairDiary.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:usesCleartextTraffic="true"
android:supportsRtl="true"
android:theme="@style/Theme.HairDiary"
tools:targetApi="31" >
<activity
android:name=".ui.activities.UserProfileActivity"
android:exported="false" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.activities.ReportCameraActivity"
android:exported="false" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.activities.TreatmentRecordsActivity"
android:exported="false" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.activities.SignupActivity"
android:exported="false" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.activities.SignInActivity"
android:exported="true" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.activities.MainActivity"
android:exported="true" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<service
android:name=".firebase.NotificationMessagingService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.HairDiary.fileProvider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
\ No newline at end of file
package com.HairDiary.adapters;
import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.HairDiary.databinding.ItemContainerRecievedMessageBinding;
import com.bumptech.glide.Glide;
import com.HairDiary.R;
import com.HairDiary.databinding.ItemContainerRecievedMessageBinding;
import com.HairDiary.databinding.ItemContainerSendMsgBinding;
import com.HairDiary.models.ChatMessage;
import com.HairDiary.utilities.ImageUtilities;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private final List<ChatMessage> chatMessages;
private final String senderId;
public static final int VIEW_TYPE_SENT = 1;
public static final int VIEW_TYPE_RECEIVED = 2;
public ChatAdapter(List<ChatMessage> chatMessages, String senderId) {
this.chatMessages = chatMessages;
this.senderId = senderId;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == VIEW_TYPE_SENT)
{
return new SentMessageViewHolder(
ItemContainerSendMsgBinding.inflate(
LayoutInflater.from(parent.getContext()),
parent,
false
)
);
}else
{
return new RecievedMessageViewHolder(
ItemContainerRecievedMessageBinding.inflate(
LayoutInflater.from(parent.getContext()),
parent,
false
)
);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == VIEW_TYPE_SENT)
{
((SentMessageViewHolder) holder).setData(chatMessages.get(position));
}else {
((RecievedMessageViewHolder) holder).setData(chatMessages.get(position));
}
}
@Override
public int getItemCount() {
return chatMessages.size();
}
@Override
public int getItemViewType(int position) {
if(chatMessages.get(position).senderId.equals(senderId))
{
return VIEW_TYPE_SENT;
}else
{
return VIEW_TYPE_RECEIVED;
}
}
static class SentMessageViewHolder extends RecyclerView.ViewHolder {
private final ItemContainerSendMsgBinding binding;
SentMessageViewHolder(ItemContainerSendMsgBinding itemContainerSendMsgBinding) {
super(itemContainerSendMsgBinding.getRoot());
binding = itemContainerSendMsgBinding;
}
void setData(ChatMessage chatMessage) {
// Check if the string matches the pattern
if (chatMessage.firebaseUrl != null) {
binding.txtMsg.setVisibility(View.GONE);
binding.imageFrameViewChat.setVisibility(View.VISIBLE);
if(chatMessage.firebaseUrl != null){
Glide.with(binding.chatImageView.getContext())
.load(chatMessage.firebaseUrl)
.into(binding.chatImageView);
}
} else {
binding.txtMsg.setVisibility(View.VISIBLE);
binding.imageFrameViewChat.setVisibility(View.GONE);
binding.txtMsg.setText(chatMessage.message);
}
binding.txtDateTime.setText(chatMessage.dateTime);
}
}
static class RecievedMessageViewHolder extends RecyclerView.ViewHolder {
private final ItemContainerRecievedMessageBinding binding;
RecievedMessageViewHolder(ItemContainerRecievedMessageBinding itemContainerRecievedMessageBinding)
{
super(itemContainerRecievedMessageBinding.getRoot());
binding = itemContainerRecievedMessageBinding;
}
void setData(ChatMessage chatMessage)
{
binding.txtMsg.setText(chatMessage.message);
binding.txtDateTime.setText(chatMessage.dateTime);
}
}
}
package com.HairDiary.adapters;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.Timestamp;
import com.HairDiary.R;
import com.HairDiary.databinding.ReportItemBinding;
import com.HairDiary.models.ReportModel;
import com.HairDiary.models.Response.ReportResponse;
import com.HairDiary.ui.fragments.SingleReportFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
public class ReportAdapter extends RecyclerView.Adapter<ReportAdapter.ReportItemViewHolder>{
private final List<ReportResponse> reportModelsList = new ArrayList<>();
private final List<Timestamp> timestampList = new ArrayList<>();
private Context context;
public ReportAdapter(Context context, TreeMap<Timestamp,ReportResponse> responseTreeMap) {
if (responseTreeMap != null){
reportModelsList.addAll(responseTreeMap.values());
timestampList.addAll(responseTreeMap.keySet());
}
this.context = context;
}
@NonNull
@Override
public ReportItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ReportItemViewHolder( ReportItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(@NonNull ReportItemViewHolder holder, int position) {
holder.setData(reportModelsList.get(position));
}
@Override
public int getItemCount() {
return reportModelsList.size();
}
public class ReportItemViewHolder extends RecyclerView.ViewHolder {
private final ReportItemBinding binding;
public ReportItemViewHolder(@NonNull ReportItemBinding inflate) {
super(inflate.getRoot());
binding = inflate;
binding.reportItemCardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction = ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.homeContainer, new SingleReportFragment(timestampList.get(getAdapterPosition())));
fragmentTransaction.addToBackStack("reportSingle"); // Add the tag for back Operations
ReportResponse.setSelectedReport(getAdapterPosition());
fragmentTransaction.commit();
}
});
}
void setData(ReportResponse reportResponse) {
binding.performSca.setText(reportResponse.getMedication_name());
binding.performScaDate.setText(reportResponse.getPrescription_date());
}
}
}
package com.HairDiary.adapters;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.HairDiary.databinding.ItemContainerSendMsgBinding;
import com.HairDiary.databinding.ScheduleItemBinding;
import com.HairDiary.models.ChatMessage;
import com.HairDiary.models.ReportModel;
import com.HairDiary.utilities.NotificationHandler;
import com.HairDiary.utilities.formatConverter;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class ScheduleAdapter extends RecyclerView.Adapter<ScheduleAdapter.ScheduleItemViewHolder>{
private final List<ReportModel> reportModelsList;
public ScheduleAdapter(List<ReportModel> reportModelsList) {
this.reportModelsList = reportModelsList;
}
@NonNull
@Override
public ScheduleAdapter.ScheduleItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ScheduleAdapter.ScheduleItemViewHolder( ScheduleItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(@NonNull ScheduleItemViewHolder holder, int position) {
holder.setData(reportModelsList.get(position));
}
@Override
public int getItemCount() {
if (reportModelsList.size() > 3)
return 4;
return reportModelsList.size();
}
public class ScheduleItemViewHolder extends RecyclerView.ViewHolder {
Calendar calendar = Calendar.getInstance();
private final ScheduleItemBinding binding;
public ScheduleItemViewHolder(ScheduleItemBinding inflate) {
super(inflate.getRoot());
binding = inflate;
calendar.setTime(new Date());
}
void setData(ReportModel reportModel) {
binding.performSca.setText(reportModel.getTitle() + "");
binding.performScaDate.setText(reportModel.getDate());
}
}
}
package com.HairDiary.adapters;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.CalendarView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;
import com.HairDiary.R;
import com.HairDiary.databinding.CalenderDialogBinding;
import com.HairDiary.databinding.ScheduleEditItemBinding;
import com.HairDiary.models.ReportModel;
import com.HairDiary.models.Response.ReportResponse;
import com.HairDiary.utilities.formatConverter;
import java.util.List;
public class ScheduleEditAdapter extends RecyclerView.Adapter<ScheduleEditAdapter.ScheduleEditItemViewHolder>{
public static List<ReportModel> reportModelsList;
public ScheduleEditAdapter(List<ReportModel> reportModelsList) {
ScheduleEditAdapter.reportModelsList = reportModelsList;
}
@NonNull
@Override
public ScheduleEditAdapter.ScheduleEditItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ScheduleEditAdapter.ScheduleEditItemViewHolder( ScheduleEditItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(@NonNull ScheduleEditAdapter.ScheduleEditItemViewHolder holder, int position) {
holder.setData(reportModelsList.get(position));
}
@Override
public int getItemCount() {
return reportModelsList.size();
}
public class ScheduleEditItemViewHolder extends RecyclerView.ViewHolder {
private final ScheduleEditItemBinding binding;
private final Object object = new Object();
public ScheduleEditItemViewHolder(ScheduleEditItemBinding inflate) {
super(inflate.getRoot());
binding = inflate;
binding.reportItemCardView.setVisibility(View.VISIBLE);
binding.calenderImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
LayoutInflater inflater = LayoutInflater.from(v.getContext());
CalenderDialogBinding calenderBinding = CalenderDialogBinding.bind(inflater.inflate(R.layout.calender_dialog, null));
builder.setView(calenderBinding.getRoot());
AlertDialog dialog = builder.create();
calenderBinding.calendarView.setDate(formatConverter.stringToDate(binding.performScaDate.getText().toString()).getTime());
calenderBinding.calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
@Override
public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) {
reportModelsList.get(getAdapterPosition()).setDate(formatConverter.formatDateString(year, month, dayOfMonth));
binding.performScaDate.setText(reportModelsList.get(getAdapterPosition()).getDate());
dialog.dismiss(); // This will close the dialog
}
});
dialog.show();
}
});
binding.performSca.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
reportModelsList.get(getAdapterPosition()).setTitle(s.toString());
}
});
binding.reportItemCardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
binding.performSca.requestFocus();
binding.performSca.selectAll();
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(binding.performSca, InputMethodManager.SHOW_IMPLICIT);
}
});
binding.deleteCardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
System.out.println("Position : " + position);
synchronized (object){
if (position < reportModelsList.size()) {
reportModelsList.remove(position);
notifyDataSetChanged();
}
}
}
});
}
void setData(ReportModel reportModel) {
binding.performSca.setText(reportModel.getTitle());
binding.performScaDate.setText(reportModel.getDate());
}
}
public void addItem(){
reportModelsList.add(new ReportModel("Add Your Title Here", formatConverter.formatDateString(System.currentTimeMillis())));
notifyItemInserted(reportModelsList.size());
}
public void deleteItems(){
if (reportModelsList.size()>0){
reportModelsList.remove(0);
notifyItemRemoved(0);
}
}
public void addItem(ReportModel reportModel) {
reportModelsList.add(reportModel);
notifyItemInserted(reportModelsList.size());
}
}
package com.HairDiary.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.HairDiary.R;
public class SelectProfileAdapter extends BaseAdapter {
private Context context;
public SelectProfileAdapter(Context context) {
this.context = context;
}
@Override
public int getCount() {
return 3; // Number of profiles
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.profile_layout, parent, false);
}
// Customize the profile item view here
ImageView imgProPic = convertView.findViewById(R.id.imgProPic);
// Set image resource and other attributes
return convertView;
}
}
package com.HairDiary.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.HairDiary.R;
import com.HairDiary.models.TreatmentRecord;
import java.util.ArrayList;
public class TreatmentRecordsAdapter extends RecyclerView.Adapter<TreatmentRecordsAdapter.TreatmentRecordViewHolder> {
private final ArrayList<TreatmentRecord> treatmentRecordList = TreatmentRecord.getInstance();
public TreatmentRecordsAdapter() {
}
@Override
public TreatmentRecordsAdapter.TreatmentRecordViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.item_treatment_record, parent, false);
return new TreatmentRecordViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull TreatmentRecordViewHolder holder, int position) {
holder.bindRecord(treatmentRecordList.get(position));
}
@Override
public int getItemCount() {
return treatmentRecordList.size();
}
public static class TreatmentRecordViewHolder extends RecyclerView.ViewHolder {
public TextView recordTreatmentTitle, recordTreatmentDescription, recordTimeStamp;
public TreatmentRecordViewHolder(@NonNull View itemView) {
super(itemView);
recordTreatmentTitle = itemView.findViewById(R.id.recordTreatmentTitle);
recordTreatmentDescription = itemView.findViewById(R.id.recordTreatmentDescription);
recordTimeStamp = itemView.findViewById(R.id.recordTimeStamp);
}
public void bindRecord(TreatmentRecord model) {
recordTimeStamp.setText(model.getDate());
recordTreatmentTitle.setText(model.getTitle());
recordTreatmentDescription.setText(model.getDescription());
}
}
}
package com.HairDiary.firebase;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.HairDiary.R;
import com.HairDiary.ui.activities.MainActivity;
import com.HairDiary.ui.activities.ReportCameraActivity;
public class NotificationMessagingService extends FirebaseMessagingService {
public static String refreshedToken;
@Override
public void onNewToken(@NonNull String token) {
super.onNewToken(token);
refreshedToken = token;
}
@Override
public void onMessageReceived(@NonNull RemoteMessage message) {
super.onMessageReceived(message);
sendNotification(message.getNotification().getTitle(), message.getNotification().getBody());
}
public void sendNotification(String title, String messageBody) {
// Implement notification creation and display logic here.
// You can use NotificationCompat to create and display notifications.
// Create an intent to open your app's main activity when the notification is clicked
Intent intent = new Intent(NotificationMessagingService.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Clear other activities when opened
PendingIntent pendingIntent = PendingIntent.getActivity(NotificationMessagingService.this, 100, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
// Create a notification
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(NotificationMessagingService.this, "channel_id")
.setSmallIcon(R.drawable.chat_bot_white) // Set your notification icon
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true) // Dismiss the notification when clicked
.setContentIntent(pendingIntent);
// Get the NotificationManager
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// You may need to create a notification channel if targeting Android Oreo (API level 26) and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("channel_id",
"Channel Name",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
// Show the notification
notificationManager.notify(100 /* ID of notification */, notificationBuilder.build());
}
}
package com.HairDiary.firebase;
import static com.HairDiary.utilities.formatConverter.formatTimeDifference;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.HairDiary.R;
import com.HairDiary.models.Device;
public class RealtimeDatabase {
private static View view;
private static FirebaseDatabase realTimeDatabase;
public static void setDeviceEventListener(View view){
RealtimeDatabase.view = view;
realTimeDatabase = FirebaseDatabase.getInstance("https://hairdiary-74048-default-rtdb.firebaseio.com");
// Attach the ValueEventListener to listen for changes in the device status
DatabaseReference reference = realTimeDatabase.getReference("1688454975");
reference.addValueEventListener(deviceEventListener);
}
private static final ValueEventListener deviceEventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
// This method is called whenever data at this location is updated.
DataSnapshot statusSnapshot = snapshot.child("status");
String remoteDeviceName = String.valueOf(statusSnapshot.child("device_name").getValue());
String batteryLevel = String.valueOf(statusSnapshot.child("battery").getValue());
String hairCondition = String.valueOf(statusSnapshot.child("classification").getValue());
boolean innerLEDStatus = (boolean) statusSnapshot.child("innerLED").getValue();
boolean isWearStatus = (boolean) statusSnapshot.child("isWear").getValue();
long lastSyncTimestamp = (long) statusSnapshot.child("lastSync").getValue();
Device device = Device.getInstance();
device.setDetails(remoteDeviceName, batteryLevel, lastSyncTimestamp, innerLEDStatus, hairCondition);
Log.d("Home", "Device Name: "+ remoteDeviceName);
Log.d("HOME", "Battery Level: " + batteryLevel);
Log.d("HOME", "Inner LED Status: " + innerLEDStatus);
Log.d("HOME", "Is Wear Status: " + isWearStatus);
Log.d("HOME", "Last Sync Timestamp: " + lastSyncTimestamp);
//1689587196
//1691998042676
TextView deviceName = view.findViewById(R.id.device_name);
TextView batteryPercent = view.findViewById(R.id.battery);
TextView connectedText = view.findViewById(R.id.connection);
TextView lastSyncTimeText = view.findViewById(R.id.sec);
TextView hairConditionText = view.findViewById(R.id.hair_condit);
TextView isWearText01 = view.findViewById(R.id.wearStatusFirst);
TextView isWearText02 = view.findViewById(R.id.wearStatusSecond);
String isWearMessage = (isWearStatus) ? "Device is Wear on head" : "Device is Not on head";
deviceName.setText(remoteDeviceName);
batteryPercent.setText(batteryLevel+"%");
connectedText.setText((innerLEDStatus)?"Connected":"Disconnected");
hairConditionText.setText(hairCondition);
isWearText01.setText(isWearMessage);
isWearText02.setText(isWearMessage);
// Calculate time difference and format it
long currentTimeMillis = System.currentTimeMillis();
System.out.println(currentTimeMillis);
String timeDifference = formatTimeDifference(currentTimeMillis - (lastSyncTimestamp*1000));
lastSyncTimeText.setText("" + timeDifference);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
// Failed to read value
System.out.println("error 404");
Log.w("HOME", "Failed to read value.", error.toException());
}
};
}
package com.HairDiary.models;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import java.util.Date;
public class ChatMessage {
public String senderId, receiverId, message, dateTime, firebaseUrl;
public Date dateObj;
@NonNull
@Override
public String toString() {
return "\n{\n\"role\":\"" + senderId +"\",\n" +
"\"content\":" + message +"\"\n}";
}
}
package com.HairDiary.models;
public class Device {
private static Device instance;
private String deviceName, battery, hairCondition;
private long timeMills;
private boolean InnerLED, isWear;
private Device() {
//set default values
this.deviceName = "device Name";
this.hairCondition = "Normal";
this.battery = "100";
this.timeMills = 1693294691956L;
this.InnerLED = false;
this.isWear = false;
}
public static Device getInstance(){
if (instance == null){
synchronized (Device.class){
if (instance == null){
instance = new Device();
}
}
}
return instance;
}
public void setDetails(String deviceName, String battery, long timeMills, boolean innerLED, String hairCondition) {
this.deviceName = deviceName;
this.battery = battery;
this.timeMills = timeMills;
this.InnerLED = innerLED;
this.hairCondition = hairCondition;
}
public String getHairCondition() {
return hairCondition;
}
public boolean isWear() {
return isWear;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getBattery() {
return battery;
}
public void setBattery(String battery) {
this.battery = battery;
}
public long getTimeMills() {
return timeMills;
}
public void setTimeMills(long timeMills) {
this.timeMills = timeMills;
}
public boolean isInnerLED() {
return InnerLED;
}
public void setInnerLED(boolean innerLED) {
InnerLED = innerLED;
}
}
package com.HairDiary.models;
import java.util.Date;
public class ReportModel {
private static long availableReportId = 0;
private long reportId;
String title, date;
public Date dateObj;
public ReportModel(String title, String date) {
this.title = title;
this.date = date;
reportId = ++ReportModel.availableReportId;
}public ReportModel(String title, String date, long reportID) {
this.title = title;
this.date = date;
this.reportId = reportID;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Date getDateObj() {
return dateObj;
}
public void setDateObj(Date dateObj) {
this.dateObj = dateObj;
}
public static void setAvailableReportId(long availableReportId) {
ReportModel.availableReportId = availableReportId;
}
public long getReportId() {
return reportId;
}
public void setReportId(long reportId) {
this.reportId = reportId;
}
@Override
public String toString() {
return "Report ID: " + reportId + "\n" +
"Title: " + title + "\n" +
"Date: " + date;
}
}
package com.HairDiary.models.Response;
public class ChatResponse {
private String response;
// Constructor
public ChatResponse(String response) {
this.response = response;
}
// Getter and setter for the 'response' field
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
@Override
public String toString() {
return "ChatResponse{" +
"response='" + response + '\'' +
'}';
}
}
package com.HairDiary.models.Response;
import com.google.firebase.Timestamp;
import java.util.TreeMap;
public class ReportResponse {
private String prescription_no;
private String name;
private String allergies;
private String notable_health_condition;
// private String disease;
// private String severity;
// private String duration;
// private String treatment_period;
// private String treatment;
private String medication_name;
private String purpose;
private String dosage;
private String route;
private String frequency;
private String interval;
private String physician_name;
private String prescription_date;
private String phone_number;
private String comments;
private String age;
private String gender;
private static int selectedReport = 0;
private static TreeMap<Timestamp,ReportResponse> reportTreeMap;
private final static int maxEntry = 10;
public ReportResponse(){
}
public static TreeMap<Timestamp,ReportResponse> getReportTreeMap(){
if (reportTreeMap == null){
// TreeMap<Timestamp,ReportResponse> reportTreeMap = new TreeMap<Timestamp,ReportResponse>() ;
// reportTreeMap.put(Timestamp.now(), new ReportResponse());
return null;
}
return reportTreeMap;
}
public static void setReportTreeMap(Timestamp timestamp, ReportResponse reportResponse){
if (reportTreeMap != null){
if (reportTreeMap.size() == maxEntry){
reportTreeMap.pollFirstEntry();
}
} else {
reportTreeMap = new TreeMap<>();
}
reportTreeMap.put(timestamp,reportResponse);
}
public static int getSelectedReport() {
return selectedReport;
}
public static void setSelectedReport(int selectedReport) {
ReportResponse.selectedReport = selectedReport;
}
public String getName() {
return name;
}
public String getMedication_name() {
return medication_name;
}
public String getPrescription_date() {
return prescription_date;
}
public String getPrescription_no() {
return prescription_no;
}
public String getAllergies() {
return allergies;
}
public String getNotable_health_condition() {
return notable_health_condition;
}
public String getPurpose() {
return purpose;
}
public String getDosage() {
return dosage;
}
public String getRoute() {
return route;
}
public String getFrequency() {
return frequency;
}
public String getInterval() {
return interval;
}
public String getPhysician_name() {
return physician_name;
}
public String getPhone_number() {
return phone_number;
}
public String getComments() {
return comments;
}
@Override
public String toString() {
return "Prescription No: " + prescription_no + "\n" +
"Name: " + name + "\n" +
"Allergies: " + allergies + "\n" +
"Notable Health Condition: " + notable_health_condition + "\n" +
// "Disease: " + disease + "\n" +
// "Severity: " + severity + "\n" +
// "Duration: " + duration + "\n" +
// "Treatment Period: " + treatment_period + "\n" +
// "Treatment: " + treatment + "\n" +
"Medication Name: " + medication_name + "\n" +
"Purpose: " + purpose + "\n" +
"Dosage: " + dosage + "\n" +
"Route: " + route + "\n" +
"Frequency: " + frequency + "\n" +
"Interval: " + interval + "\n" +
"Physician Name: " + physician_name + "\n" +
"Prescription Date: " + prescription_date + "\n"+
"Phone Number: " + phone_number + "\n" +
"Additional Comments: " + comments + "\n";
}
public ReportResponse(String prescriptionNo, String name, String allergies,
String notableHealthCondition, String medicationName,
String purpose, String dosage, String route,
String frequency, String interval, String physicianName,
String prescriptionDate, String phone_number, String comments) {
this.prescription_no = prescriptionNo;
this.name = name;
this.allergies = allergies;
this.notable_health_condition = notableHealthCondition;
this.medication_name = medicationName;
this.purpose = purpose;
this.dosage = dosage;
this.route = route;
this.frequency = frequency;
this.interval = interval;
this.physician_name = physicianName;
this.prescription_date = prescriptionDate;
this.phone_number = phone_number;
this.comments = comments;
}
public void setPrescription_no(String prescription_no) {
this.prescription_no = prescription_no;
}
public void setName(String name) {
this.name = name;
}
public void setAllergies(String allergies) {
this.allergies = allergies;
}
public void setNotable_health_condition(String notable_health_condition) {
this.notable_health_condition = notable_health_condition;
}
public void setMedication_name(String medication_name) {
this.medication_name = medication_name;
}
public void setPurpose(String purpose) {
this.purpose = purpose;
}
public void setDosage(String dosage) {
this.dosage = dosage;
}
public void setRoute(String route) {
this.route = route;
}
public void setFrequency(String frequency) {
this.frequency = frequency;
}
public void setInterval(String interval) {
this.interval = interval;
}
public void setPhysician_name(String physician_name) {
this.physician_name = physician_name;
}
public void setPrescription_date(String prescription_date) {
this.prescription_date = prescription_date;
}
public void setPhone_number(String phone_number) {
this.phone_number = phone_number;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public static void clearRecords(){
if (reportTreeMap != null)
reportTreeMap.clear();
}
}
package com.HairDiary.models.Response;
public class TreatmentResponse {
private String Allergy;
private String Disease;
private String Description;
private String Medications;
private static TreatmentResponse instance;
public static TreatmentResponse getInstance(){
if (instance == null){
synchronized (TreatmentResponse.class){
instance = new TreatmentResponse();
}
}
return instance;
}
public static void setInstance(TreatmentResponse objectResponse){
instance = objectResponse;
}
public TreatmentResponse(String Description, String Medications) {
this.Description = Description;
this.Medications = Medications;
}
public TreatmentResponse() {
}
// Getters and setters for each field
public String getAllergy() {
return Allergy;
}
public void setAllergy(String Allergy) {
this.Allergy = Allergy;
}
public String getDisease() {
return Disease;
}
public void setDisease(String Disease) {
this.Disease = Disease;
}
public String getDescription() {
return Description;
}
public void setDescription(String Description) {
this.Description = Description;
}
public String getMedications() {
return Medications;
}
public void setMedications(String Medications) {
this.Medications = Medications;
}
@Override
public String toString() {
return "TreatmentResponseDTO{" +
"Allergy='" + Allergy + '\'' +
", Disease='" + Disease + '\'' +
", Description='" + Description + '\'' +
", Medications='" + Medications + '\'' +
'}';
}
}
package com.HairDiary.models;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.HairDiary.utilities.NotificationHandler;
import java.util.Calendar;
import java.util.Date;
import java.util.TreeMap;
public class ScheduledItems extends TreeMap<Long, ReportModel> {
private static ScheduledItems instance;
Date today, tomorrow;
private ScheduledItems() {
super();
}
public static ScheduledItems getInstance(){
if (instance == null)
synchronized (ScheduledItems.class){
if (instance == null){
instance = new ScheduledItems();
}
}
return instance;
}
@Nullable
@Override
public ReportModel put(Long key, ReportModel value) {
super.put(key, value);
cleanupOldData();
return value;
}
private void cleanupOldData() {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
// Set the time to 00:00:00.000
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
today = calendar.getTime();
calendar.add(Calendar.DAY_OF_YEAR, 1); // Move to tomorrow
tomorrow = calendar.getTime();
while (!isEmpty()) {
Date firstKey = new Date(firstKey());
if (!firstKey.equals(today) && firstKey.before(today)) {
remove(firstKey.getTime());
} else {
break; // Stop if we encounter entries
}
}
}
public void notifyAppointments(){
if (containsKey(today.getTime())) {
NotificationHandler.sendNotification("Schedule Alert!!", "You have an appointment on Today",100);
}
if (containsKey(tomorrow.getTime())) {
NotificationHandler.sendNotification("Schedule Alert!!", "You have an appointment on Tomorrow",101);
}
}
@Override
public void clear() {
super.clear();
}
@NonNull
@Override
public String toString() {
String printString = "";
for (ReportModel model : this.values()) {
printString += "Model : "+ model.getReportId()+"\n Title : "+model.getTitle()+"\n Date : "+model.getDate()+"\n";
}
return printString;
}
}
package com.HairDiary.models;
import com.HairDiary.utilities.formatConverter;
import java.util.ArrayList;
import java.util.Date;
public class TreatmentRecord {
private static ArrayList<TreatmentRecord> instance;
private String title, description, date;
private Date dateObj;
public static ArrayList<TreatmentRecord> getInstance() {
if(instance == null){
instance = new ArrayList<>();
}
return instance;
}
private TreatmentRecord() {
}
public TreatmentRecord(String title, String description, Date dateObj) {
this.title = title;
this.description = description;
this.dateObj = dateObj;
this.date = formatConverter.formatDateToString(dateObj);
}
public static ArrayList<TreatmentRecord> addTreatmentRecord(TreatmentRecord treatmentRecord){
if (instance == null){
instance = new ArrayList<>();
}
instance.add(treatmentRecord);
return instance;
}
public static void clearRecordArrayList(){
if (instance == null){
instance = new ArrayList<>();
}
instance.clear();
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public String getDate() {
return date;
}
public Date getDateObj() {
return dateObj;
}
}
package com.HairDiary.models;
import java.io.Serializable;
public class User implements Serializable {
public String name, email, token, id;
}
package com.HairDiary.ui.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.HairDiary.R;
import com.HairDiary.firebase.NotificationMessagingService;
import com.HairDiary.ui.fragments.ChatFragment;
import com.HairDiary.ui.fragments.DeviceFragment;
import com.HairDiary.ui.fragments.HomeFragment;
import com.HairDiary.ui.fragments.ReportFragment;
import com.HairDiary.ui.fragments.TreatmentFragment;
import com.HairDiary.ui.fragments.UserFragment;
import com.HairDiary.utilities.NotificationHandler;
public class MainActivity extends AppCompatActivity {
static BottomNavigationView nav;
//TODO: make prescription no textview & Notification for previous day.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nav = findViewById(R.id.bottomNav);
HomeFragment homeFragment = new HomeFragment();
Fragment deviceFragment = new DeviceFragment();
Fragment treatmentFragment = new TreatmentFragment();
Fragment chatFragment = new ChatFragment();
Fragment reportFragment = new ReportFragment();
Fragment userFragment = new UserFragment();
nav.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
System.out.println("stack count : "+getSupportFragmentManager().getBackStackEntryCount());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
switch (item.getItemId())
{
case R.id.home:
fragmentTransaction.replace(R.id.homeContainer, homeFragment);
fragmentTransaction.addToBackStack("home"); // Add the tag for back Operations
fragmentTransaction.commit();
return true;
case R.id.treatment:
// fragmentTransaction.replace(R.id.homeContainer, deviceFragment);
fragmentTransaction.replace(R.id.homeContainer, treatmentFragment);
fragmentTransaction.addToBackStack("treatment"); // Add the tag for back Operations
fragmentTransaction.commit();
return true;
case R.id.chat:
fragmentTransaction.replace(R.id.homeContainer, chatFragment);
fragmentTransaction.addToBackStack("chat"); // Add the tag for back Operations
fragmentTransaction.commit();
return true;
case R.id.report:
fragmentTransaction.replace(R.id.homeContainer, reportFragment);
fragmentTransaction.addToBackStack("report"); // Add the tag for back Operations
fragmentTransaction.commit();
return true;
case R.id.user:
fragmentTransaction.replace(R.id.homeContainer, userFragment);
fragmentTransaction.addToBackStack("user"); // Add the tag for back Operations
fragmentTransaction.commit();
return true;
}
return false;
}
});
//Select the home icon on the menu
nav.setSelectedItemId(R.id.home);
}
public static void setNavbar(int id){
nav.setSelectedItemId(id);
}
@Override
public void onBackPressed() {
System.out.println("begin count : "+getSupportFragmentManager().getBackStackEntryCount());
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count > 1){
getSupportFragmentManager().popBackStack();
String fragmentTag = getSupportFragmentManager().getBackStackEntryAt(count-2).getName();
nav.setSelectedItemId(getFragmentIdByTag(fragmentTag));
getSupportFragmentManager().popBackStack();
}else {
//Finish the activity when user pressed the back button in the home screen.
finish();
}
}
private int getFragmentIdByTag(String fragmentTag){
int itemId = 0; // Initialize with a default value
switch (fragmentTag) {
case "treatment":
itemId = R.id.treatment;
break;
case "chat":
itemId = R.id.chat;
break;
case "report":
itemId = R.id.report;
break;
case "user":
itemId = R.id.user;
break;
default:
itemId = R.id.home;
break;
}
return itemId;
}
@Override
protected void onStart() {
super.onStart();
NotificationHandler notificationHandler = new NotificationHandler(getApplicationContext());
}
}
\ No newline at end of file
package com.HairDiary.ui.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Patterns;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.HairDiary.R;
import com.HairDiary.databinding.ActivitySignInBinding;
import com.HairDiary.utilities.Constants;
import com.HairDiary.utilities.PreferenceManager;
import com.HairDiary.utilities.UserCalculation;
import com.HairDiary.utilities.formatConverter;
public class SignInActivity extends AppCompatActivity {
private ActivitySignInBinding binding;
private PreferenceManager preferenceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySignInBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
preferenceManager = new PreferenceManager(getApplicationContext());
setListeners();
}
@Override
protected void onStart() {
super.onStart();
// Test case ::
// preferenceManager.putBoolean(Constants.KEY_IS_SIGNED_IN, false);
// Check the user logged in previously and if it is true logged in the user.
if (preferenceManager.getBoolean(Constants.KEY_IS_SIGNED_IN)){
Intent intent = new Intent(SignInActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}else{
showToast("Please Sign In");
}
}
private void setListeners() {
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
binding.txtCreateNewAccount.setOnClickListener(view ->
startActivity(new Intent(getApplicationContext(), SignupActivity.class)));
binding.btnSignIn.setOnClickListener(v -> {
if (isValidSignInDetails())
{
firebaseAuth.signInWithEmailAndPassword(binding.inputEmail.getText().toString(), binding.inputPassword.getText().toString()).addOnCompleteListener((task -> {
if(task.isSuccessful())
{
if(firebaseAuth.getCurrentUser().isEmailVerified())
{
signIn();
}else{
showToast("Please verify your email id.");
}
}else{
Toast.makeText(SignInActivity.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}));
}
});
binding.txtForgetPw.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(SignInActivity.this);
View dialogView = getLayoutInflater().inflate(R.layout.dialog_forget, null);
EditText emailBox = dialogView.findViewById(R.id.emailBox);
builder.setView(dialogView);
AlertDialog dialog = builder.create();
dialogView.findViewById(R.id.btnReset).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String userEmail = emailBox.getText().toString();
if (TextUtils.isEmpty(userEmail) && !Patterns.EMAIL_ADDRESS.matcher(userEmail).matches())
{
Toast.makeText(SignInActivity.this, "Enter your registered email id", Toast.LENGTH_SHORT).show();
return;
}
firebaseAuth.sendPasswordResetEmail(userEmail).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful())
{
Toast.makeText(SignInActivity.this, "Check your email", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
else{
Toast.makeText(SignInActivity.this, "Send failed, Unable to send.", Toast.LENGTH_SHORT).show();
}
}
});
}
});
dialogView.findViewById(R.id.btnCancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
if (dialog.getWindow() != null)
{
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
}
dialog.show();
}
});
}
private void loading(Boolean isLoading) {
if(isLoading)
{
binding.btnSignIn.setVisibility(View.INVISIBLE);
binding.progressBar.setVisibility(View.VISIBLE);
}else
{
binding.progressBar.setVisibility(View.INVISIBLE);
binding.btnSignIn.setVisibility(View.VISIBLE);
}
}
private void signIn() {
loading(true);
FirebaseFirestore database = FirebaseFirestore.getInstance();
database.collection(Constants.KEY_COLLECTION_USERS)
.whereEqualTo(Constants.KEY_EMAIL, binding.inputEmail.getText().toString())
.whereEqualTo(Constants.KEY_PASSWORD, binding.inputPassword.getText().toString())
.get()
.addOnCompleteListener(task -> {
if (task.isSuccessful() && task.getResult() != null
&& task.getResult().getDocuments().size() > 0)
{
DocumentSnapshot documentSnapshot = task.getResult().getDocuments().get(0);
System.out.println(documentSnapshot);
preferenceManager.putBoolean(Constants.KEY_IS_SIGNED_IN, true);
preferenceManager.putString(Constants.KEY_USER_ID, documentSnapshot.getId());
preferenceManager.putString(Constants.KEY_NAME, documentSnapshot.getString(Constants.KEY_NAME));
preferenceManager.putString(Constants.KEY_USER_GENDER, documentSnapshot.getString(Constants.KEY_USER_GENDER));
preferenceManager.putString(Constants.KEY_USER_DOB, documentSnapshot.getString(Constants.KEY_USER_DOB));
int Age = UserCalculation.ageCalculator(formatConverter.stringToDate(documentSnapshot.getString(Constants.KEY_USER_DOB)));
preferenceManager.putInt(Constants.KEY_USER_AGE, Age);
if (documentSnapshot.contains(Constants.KEY_MOBILE)){
preferenceManager.putString(Constants.KEY_MOBILE, documentSnapshot.getString(Constants.KEY_MOBILE));
}
Intent intent = new Intent(SignInActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}else
{
loading(false);
showToast("Unable to Sign In");
}
});
}
private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
private Boolean isValidSignInDetails() {
if (binding.inputEmail.getText().toString().trim().isEmpty())
{
showToast("Enter email");
return false;
}else if(!Patterns.EMAIL_ADDRESS.matcher(binding.inputEmail.getText().toString()).matches())
{
showToast("Enter valid email");
return false;
}else if (binding.inputPassword.getText().toString().trim().isEmpty())
{
showToast("Enter password");
return false;
}else
{
return true;
}
}
}
\ No newline at end of file
package com.HairDiary.ui.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.app.DatePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.CalendarView;
import android.widget.DatePicker;
import android.widget.Toast;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.FirebaseFirestore;
import com.HairDiary.R;
import com.HairDiary.databinding.ActivitySignupBinding;
import com.HairDiary.databinding.CalenderDialogBinding;
import com.HairDiary.utilities.Constants;
import com.HairDiary.utilities.PreferenceManager;
import com.HairDiary.utilities.UserCalculation;
import com.HairDiary.utilities.formatConverter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
public class SignupActivity extends AppCompatActivity {
private ActivitySignupBinding binding;
private PreferenceManager preferenceManager;
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySignupBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
preferenceManager = new PreferenceManager(getApplicationContext());
init();
setListeners();
}
private void init(){
ArrayList<String> genderList = new ArrayList<>();
genderList.add("Male");
genderList.add("Female");
// Create an ArrayAdapter with your gender options
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,genderList);
binding.inputGender.setAdapter(adapter);
binding.inputGender.setText(genderList.get(0), false);
binding.inputDOB.setText("2000-06-26");
}
private void setListeners() {
binding.txtSignIn.setOnClickListener(v -> onBackPressed());
binding.btnSignUp.setOnClickListener(v -> {
if (isValidSignUpDetails()) {
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
firebaseAuth.createUserWithEmailAndPassword(binding.inputEmail.getText().toString(), binding.inputPassword.getText().toString()).addOnCompleteListener((task -> {
if (task.isSuccessful()) {
signUp();
}else {
Toast.makeText(SignupActivity.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
System.out.println(task.getException().getMessage());
}
}));
} else{
showToast("Please Enter Valid Details!!");
}
});
binding.inputDOB.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus){
calenderPicker(v);
}
}
});
binding.inputDOB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
calenderPicker(v);
}
});
}
private void calenderPicker(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
LayoutInflater inflater = LayoutInflater.from(v.getContext());
CalenderDialogBinding calenderBinding = CalenderDialogBinding.bind(inflater.inflate(R.layout.calender_dialog, null));
builder.setView(calenderBinding.getRoot());
// Get the current date from your EditText (or set a default date)
String currentDateString = binding.inputDOB.getText().toString();
Calendar calendar = Calendar.getInstance();
if (!currentDateString.isEmpty()) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
try {
calendar.setTime(sdf.parse(currentDateString));
} catch (ParseException e) {
e.printStackTrace();
}
}
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(
v.getContext(),
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDayOfMonth) {
calendar.set(selectedYear, selectedMonth, selectedDayOfMonth);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.UK);
String formattedDate = sdf.format(calendar.getTime());
binding.inputDOB.setText(formattedDate);
}
},
year,
month,
day
);
datePickerDialog.show();
}
private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
private void signUp() {
loading(true);
FirebaseFirestore database = FirebaseFirestore.getInstance();
HashMap<String, Object> user = new HashMap<>();
user.put(Constants.KEY_NAME, binding.inputName.getText().toString());
user.put(Constants.KEY_EMAIL, binding.inputEmail.getText().toString());
user.put(Constants.KEY_PASSWORD, binding.inputPassword.getText().toString());
user.put(Constants.KEY_USER_GENDER, binding.inputGender.getText().toString());
user.put(Constants.KEY_USER_DOB, binding.inputDOB.getText().toString());
database.collection(Constants.KEY_COLLECTION_USERS)
.add(user)
.addOnSuccessListener(documentReference -> {
loading(true);
preferenceManager.putBoolean(Constants.KEY_IS_SIGNED_IN, true);
preferenceManager.putString(Constants.KEY_USER_ID, firebaseAuth.getUid());
preferenceManager.putString(Constants.KEY_NAME, binding.inputName.getText().toString());
preferenceManager.putString(Constants.KEY_USER_GENDER, binding.inputGender.getText().toString());
preferenceManager.putString(Constants.KEY_USER_DOB, binding.inputDOB.getText().toString());
int Age = UserCalculation.ageCalculator(formatConverter.stringToDate( binding.inputDOB.getText().toString()));
preferenceManager.putInt(Constants.KEY_USER_AGE, Age);
firebaseAuth.getCurrentUser().sendEmailVerification().addOnCompleteListener(emailVerificationTask -> {
if (emailVerificationTask.isSuccessful()) {
showToast("Register successfully. Please verify your email.");
} else {
showToast("Failed to send verification email. Please use forget password");
}
// Proceed to your next activity or display a message
Intent intent = new Intent(getApplicationContext(), SignInActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
});
})
.addOnFailureListener(exception -> {
loading(false);
showToast(exception.getMessage());
});
}
private Boolean isValidSignUpDetails() {
if(binding.inputName.getText().toString().trim().isEmpty()) {
binding.inputName.setError("Enter name");
return false;
}else if (binding.inputEmail.getText().toString().trim().isEmpty()) {
binding.inputEmail.setError("Enter Email");
return false;
}else if (!Patterns.EMAIL_ADDRESS.matcher(binding.inputEmail.getText().toString()).matches()) {
binding.inputEmail.setError("Enter a valid Email");
return false;
}else if (binding.inputPassword.getText().toString().trim().isEmpty()) {
binding.inputPassword.setError("Enter password");
return false;
}else if (binding.confirmPassword.getText().toString().trim().isEmpty()) {
binding.confirmPassword.setError("Confirm your password");
return false;
}else if (!binding.inputPassword.getText().toString().equals(binding.confirmPassword.getText().toString())) {
binding.confirmPassword.setError("Password and Confirm password must be the same");
return false;
}else {
return true;
}
}
private void loading(Boolean isLoading) {
if(isLoading) {
binding.btnSignUp.setVisibility(View.INVISIBLE);
binding.progressBar.setVisibility(View.VISIBLE);
}else {
binding.progressBar.setVisibility(View.INVISIBLE);
binding.btnSignUp.setVisibility(View.VISIBLE);
}
}
}
\ No newline at end of file
package com.HairDiary.ui.activities;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.HairDiary.adapters.TreatmentRecordsAdapter;
import com.HairDiary.databinding.ActivityTreatmentRecordsBinding;
import com.HairDiary.firebase.FirestoreDatabase;
import com.HairDiary.models.TreatmentRecord;
import com.HairDiary.utilities.Constants;
import com.HairDiary.utilities.PreferenceManager;
public class TreatmentRecordsActivity extends AppCompatActivity {
private ActivityTreatmentRecordsBinding binding;
private PreferenceManager preferenceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityTreatmentRecordsBinding.inflate(getLayoutInflater());
preferenceManager = new PreferenceManager(this);
setContentView(binding.getRoot());
init();
setListeners();
}
private void init() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
binding.treatmentRecyclerView.setLayoutManager(layoutManager);
FirestoreDatabase.retrieveTreatmentRecords(binding.treatmentRecordsProgressBar,
binding.treatmentRecyclerView,
preferenceManager.getString(Constants.KEY_USER_ID));
TreatmentRecordsAdapter treatmentRecordsAdapter = new TreatmentRecordsAdapter();
binding.treatmentRecyclerView.setAdapter(treatmentRecordsAdapter);
}
private void setListeners() {
}
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
TreatmentRecord.clearRecordArrayList();
}
}
package com.HairDiary.ui.activities;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.Toast;
import com.github.dhaval2404.imagepicker.ImagePicker;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.HairDiary.R;
import com.HairDiary.databinding.ActivityUserProfileBinding;
import com.HairDiary.databinding.CalenderDialogBinding;
import com.HairDiary.databinding.FragmentHomeNewBinding;
import com.HairDiary.ui.fragments.ChatFragment;
import com.HairDiary.utilities.Constants;
import com.HairDiary.utilities.PreferenceManager;
import com.HairDiary.utilities.UserCalculation;
import com.HairDiary.utilities.formatConverter;
import org.checkerframework.checker.units.qual.C;
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
public class UserProfileActivity extends AppCompatActivity {
private ActivityUserProfileBinding binding;
private PreferenceManager preferenceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityUserProfileBinding.inflate(getLayoutInflater());
preferenceManager = new PreferenceManager(this);
setContentView(binding.getRoot());
init();
setListeners();
}
private void init() {
String uri = preferenceManager.getString(Constants.KEY_PROFILE_IMAGE);
if ( uri!= null){
binding.imgProPic.setImageURI(Uri.parse(uri));
//make the add image-text visibility gone when having picture
binding.txtAddImage.setVisibility(View.GONE);
}
ArrayList<String> genderList = new ArrayList<>();
genderList.add("Male");
genderList.add("Female");
// Create an ArrayAdapter with your gender options
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,genderList);
binding.gender.setAdapter(adapter);
binding.gender.setText(preferenceManager.getString(Constants.KEY_USER_GENDER), false);
binding.inputProfileDOB.setText(preferenceManager.getString(Constants.KEY_USER_DOB));
binding.inputNum.setText(preferenceManager.getString(Constants.KEY_MOBILE));
}
private void setListeners() {
binding.imgProPic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ImagePicker.with(UserProfileActivity.this)
.crop()
.galleryOnly()
.createIntent(intent -> {
imagePickerLauncher.launch(intent);
return null;
});
}
});
binding.inputProfileDOB.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus){
calenderPicker(v);
}
}
});
binding.inputProfileDOB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
calenderPicker(v);
}
});
binding.btnCreate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
binding.btnCreate.setFocusable(false);
binding.progressBar.setVisibility(View.VISIBLE);
updateFirebaseUser();
}
});
}
private final ActivityResultLauncher<Intent> imagePickerLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
assert data != null;
Uri uri = data.getData();
System.out.println(uri);
binding.imgProPic.setImageURI(uri);
preferenceManager.putString(Constants.KEY_PROFILE_IMAGE,uri.toString());
//make the add image-text visibility gone when having picture
binding.txtAddImage.setVisibility(View.GONE);
} else if (result.getResultCode() == ImagePicker.RESULT_ERROR) {
showToast(ImagePicker.getError(result.getData()));
} else {
showToast("Task Cancelled");
}
}
);
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
@Override
protected void onPause() {
super.onPause();
updateFirebaseUser();
}
private void updateFirebaseUser(){
System.out.println("User Updated");
//TODO: update the firebase and Local settings with changed data
int Age = UserCalculation.ageCalculator(formatConverter.stringToDate(binding.inputProfileDOB.getText().toString()));
preferenceManager.putInt(Constants.KEY_USER_AGE, Age);
preferenceManager.putString(Constants.KEY_USER_GENDER, binding.gender.getText().toString());
preferenceManager.putString(Constants.KEY_USER_DOB, binding.inputProfileDOB.getText().toString());
preferenceManager.putString(Constants.KEY_MOBILE, binding.inputNum.getText().toString());
FirebaseFirestore database = FirebaseFirestore.getInstance();
HashMap<String, Object> user = new HashMap<>();
user.put(Constants.KEY_USER_GENDER, binding.gender.getText().toString());
user.put(Constants.KEY_USER_DOB, binding.inputProfileDOB.getText().toString());
user.put(Constants.KEY_MOBILE, binding.inputNum.getText().toString());
new Handler().post(new Runnable() {
@Override
public void run() {
//I want to update DOB and Gender in this collection
database.collection(Constants.KEY_COLLECTION_USERS)
.document(preferenceManager.getString(Constants.KEY_USER_ID))
.update(user)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Handle the successful update here
showToast("User data updated in Firestore");
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
System.out.println("Error updating user data in Firestore: " + e.getMessage());
}
});
}
});
}
private void calenderPicker(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
LayoutInflater inflater = LayoutInflater.from(v.getContext());
CalenderDialogBinding calenderBinding = CalenderDialogBinding.bind(inflater.inflate(R.layout.calender_dialog, null));
builder.setView(calenderBinding.getRoot());
// Get the current date from your EditText (or set a default date)
String currentDateString = binding.inputProfileDOB.getText().toString();
Calendar calendar = Calendar.getInstance();
if (!currentDateString.isEmpty()) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
try {
calendar.setTime(sdf.parse(currentDateString));
} catch (ParseException e) {
e.printStackTrace();
}
}
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(
v.getContext(),
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDayOfMonth) {
calendar.set(selectedYear, selectedMonth, selectedDayOfMonth);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.UK);
String formattedDate = sdf.format(calendar.getTime());
binding.inputProfileDOB.setText(formattedDate);
}
},
year,
month,
day
);
datePickerDialog.show();
}
}
\ No newline at end of file
package com.HairDiary.ui.fragments;
import static com.HairDiary.firebase.RealtimeDatabase.setDeviceEventListener;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.HairDiary.databinding.FragmentDeviceNewBinding;
/**
* A simple {@link Fragment} subclass.
* Use the {@link DeviceFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class DeviceFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private FragmentDeviceNewBinding binding;
public DeviceFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment DeviceFragment.
*/
// TODO: Rename and change types and number of parameters
public static DeviceFragment newInstance(String param1, String param2) {
DeviceFragment fragment = new DeviceFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
binding = FragmentDeviceNewBinding.inflate(inflater);
View view = binding.getRoot();
setDeviceEventListener(binding.getRoot().getRootView());
return view;
}
}
\ No newline at end of file
package com.HairDiary.ui.fragments;
//TODO: find Some input files use or override a deprecated API.
import static com.HairDiary.firebase.RealtimeDatabase.setDeviceEventListener;
import static com.HairDiary.utilities.formatConverter.formatDateString;
import android.animation.ValueAnimator;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.os.Handler;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.HairDiary.R;
import com.HairDiary.adapters.ScheduleAdapter;
import com.HairDiary.databinding.FragmentHomeNewBinding;
import com.HairDiary.firebase.FirestoreDatabase;
import com.HairDiary.models.ReportModel;
import com.HairDiary.models.Response.ReportResponse;
import com.HairDiary.models.ScheduledItems;
import com.HairDiary.ui.activities.MainActivity;
import com.HairDiary.ui.activities.ReportCameraActivity;
import com.HairDiary.ui.activities.SignInActivity;
import com.HairDiary.ui.activities.UserProfileActivity;
import com.HairDiary.utilities.Constants;
import com.HairDiary.utilities.NotificationHandler;
import com.HairDiary.utilities.PreferenceManager;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class HomeFragment extends Fragment {
private FragmentHomeNewBinding binding;
private PreferenceManager preferenceManager;
final ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentHomeNewBinding.inflate(inflater);
View view = binding.getRoot();
preferenceManager = new PreferenceManager(requireActivity());
init();
registerForContextMenu(binding.option); // Register for the context menu
setListeners();
return view;
}
public void init(){
setDeviceEventListener(binding.getRoot().getRootView());
// Attach a LinearLayoutManager
LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
binding.ScheduleRecyclerView.setLayoutManager(layoutManager);
ScheduleAdapter ScheduleAdapter = new ScheduleAdapter(new ArrayList<>(ScheduledItems.getInstance().values()));
binding.ScheduleRecyclerView.setAdapter(ScheduleAdapter);
setAnimateWearStatus();
binding.todayDate.setText(formatDateString(System.currentTimeMillis()));
}
private void setListeners(){
binding.option.setOnClickListener(this::showContextMenu);
binding.scanNow.setOnClickListener(view -> {
Context context = getContext();
if (context != null) {
startActivity(new Intent(context, ReportCameraActivity.class));
}
});
binding.signOut.setOnClickListener(v -> {
Intent intent = new Intent(requireActivity(), SignInActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
preferenceManager.clear();
});
binding.reportLinearLayout.setOnClickListener(v -> MainActivity.setNavbar(R.id.report));
}
@Override
public void onCreateContextMenu(@NonNull ContextMenu menu, @NonNull View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
requireActivity().getMenuInflater().inflate(R.menu.menu_home, menu);
}
private void showContextMenu(View v) {
PopupMenu popupMenu = new PopupMenu(requireContext(), v);
popupMenu.getMenuInflater().inflate(R.menu.menu_home, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_item_option1) {
// Handle Option 1 click
Intent intent = new Intent(requireContext(), UserProfileActivity.class);
startActivity(intent);
return true;
} else if (id == R.id.menu_item_option2) {
// Handle Option 2 click
FragmentTransaction fragmentTransaction = requireActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.homeContainer, new DeviceFragment());
fragmentTransaction.addToBackStack("device"); // Add the tag for back Operations
fragmentTransaction.commit();
return true;
} else if (id == R.id.menu_item_option3) {
// Handle Option 3 click
Intent intent = new Intent(requireActivity(), SignInActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
preferenceManager.clear();
return true;
}
return false;
}
});
popupMenu.show();
}
@Override
public void onResume() {
super.onResume();
FirestoreDatabase.getScheduleDetails(preferenceManager.getString(Constants.KEY_USER_ID), binding.ScheduleRecyclerView);
}
@Override
public void onPause() {
super.onPause();
animator.end();
}
private void setAnimateWearStatus() {
final TextView wearStatusFirst = binding.include.wearStatusFirst;
final TextView wearStatusSecond = binding.include.wearStatusSecond;
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(7000L);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float progress = (float) animation.getAnimatedValue();
final float width = wearStatusFirst.getWidth();
final float translationX = width * progress;
wearStatusFirst.setTranslationX(translationX);
wearStatusSecond.setTranslationX(translationX - width);
}
});
animator.start();
}
@Override
public void onStart() {
super.onStart();
}
}
\ No newline at end of file
package com.HairDiary.ui.fragments;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.preference.Preference;
import android.telecom.Call;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupMenu;
import android.widget.Toast;
import com.HairDiary.models.TreatmentRecord;
import com.HairDiary.ui.activities.TreatmentRecordsActivity;
import com.google.android.material.snackbar.Snackbar;
import com.google.common.net.MediaType;
import com.HairDiary.R;
import com.HairDiary.adapters.ReportAdapter;
import com.HairDiary.adapters.ScheduleAdapter;
import com.HairDiary.databinding.FragmentHomeNewBinding;
import com.HairDiary.databinding.FragmentReportNewBinding;
import com.HairDiary.firebase.FirestoreDatabase;
import com.HairDiary.models.ReportModel;
import com.HairDiary.models.Response.ReportResponse;
import com.HairDiary.ui.activities.ReportCameraActivity;
import com.HairDiary.utilities.Constants;
import com.HairDiary.utilities.PreferenceManager;
import com.HairDiary.utilities.formatConverter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
/**
* A simple {@link Fragment} subclass.
* Use the {@link ReportFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class ReportFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private FragmentReportNewBinding binding;
private PreferenceManager preferenceManager;
public ReportFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment ReportFragment.
*/
// TODO: Rename and change types and number of parameters
public static ReportFragment newInstance(String param1, String param2) {
ReportFragment fragment = new ReportFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
binding = FragmentReportNewBinding.inflate(inflater);
preferenceManager = new PreferenceManager(requireContext());
init();
setListeners();
return binding.getRoot();
}
private void init() {
FirestoreDatabase.retrieveRecords(preferenceManager.getString(Constants.KEY_USER_ID), binding.reportRecyclerView, requireContext());
registerForContextMenu(binding.reportThreeDot);
}
private void setListeners(){
binding.reports.setOnClickListener(view -> {
Context context = getContext();
if (context != null) {
startActivity(new Intent(context, ReportCameraActivity.class));
}
});
binding.reportThreeDot.setOnClickListener(this::showContextMenu);
}
@Override
public void onResume() {
super.onResume();
if (ReportResponse.getReportTreeMap() != null) {
// Attach a LinearLayoutManager
LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
binding.reportRecyclerView.setLayoutManager(layoutManager);
ReportAdapter reportAdapter = new ReportAdapter(requireContext(), ReportResponse.getReportTreeMap());
binding.reportRecyclerView.setAdapter(reportAdapter);
}
}
private void showContextMenu(View v) {
PopupMenu popupMenu = new PopupMenu(requireContext(), v);
popupMenu.getMenuInflater().inflate(R.menu.menu_report, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_item_option) {
// Handle Option 1 click
FirestoreDatabase.clearRecords(preferenceManager.getString(Constants.KEY_USER_ID),binding.getRoot(), binding.reportRecyclerView);
return true;
}
return false;
}
});
popupMenu.show();
}
}
\ No newline at end of file
package com.HairDiary.ui.fragments;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.helper.widget.Flow;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.preference.Preference;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.TextView;
import com.github.dhaval2404.imagepicker.ImagePicker;
import com.makeramen.roundedimageview.RoundedImageView;
import com.HairDiary.R;
import com.HairDiary.adapters.SelectProfileAdapter;
import com.HairDiary.databinding.FragmentUserBinding;
import com.HairDiary.models.Device;
import com.HairDiary.models.Response.ReportResponse;
import com.HairDiary.ui.activities.ReportCameraActivity;
import com.HairDiary.ui.activities.UserProfileActivity;
import com.HairDiary.utilities.Constants;
import com.HairDiary.utilities.PreferenceManager;
public class UserFragment extends Fragment {
FragmentUserBinding binding;
PreferenceManager preferenceManager;
private AlertDialog dialog;
private GridView gridView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentUserBinding.inflate(inflater);
preferenceManager = new PreferenceManager(requireContext());
init();
setListeners();
return binding.getRoot();
}
private void init(){
Device device = Device.getInstance();
binding.btrHealth.setText(device.getBattery()+"%");
binding.txtDevice.setText(device.getDeviceName());
binding.txtName.setText(preferenceManager.getString(Constants.KEY_NAME));
String uri = preferenceManager.getString(Constants.KEY_PROFILE_IMAGE);
if ( uri!= null){
binding.imgPropic.setImageURI(Uri.parse(uri));
}
}
private void setListeners() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
View dialogView = getLayoutInflater().inflate(R.layout.select_user_dialog, null);
builder.setView(dialogView);
dialog = builder.create();
gridView = dialogView.findViewById(R.id.gridView);
gridView.setAdapter(new SelectProfileAdapter(requireContext()));
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Handle item click if needed
}
});
binding.btnRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Context context = getContext();
Intent intent = new Intent(context, UserProfileActivity.class);
startActivity(intent);
}
});
binding.addPro.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// if (dialog.getWindow() != null) {
// dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
// }
dialog.show();
}
});
binding.devBtnRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction = requireActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.homeContainer, new DeviceFragment());
fragmentTransaction.addToBackStack("device_view"); // Add the tag for back Operations
fragmentTransaction.commit();
}
});
}
}
\ No newline at end of file
package com.HairDiary.utilities;
public class Constants {
public static final String BASE_URL = "http://192.168.8.102:8000";
public static final String KEY_PROJECT_ID = "hairdiary-74048";
public static final String KEY_COLLECTION_USERS = "users";
public static final String KEY_CHAT_USER = "user";
public static final String KEY_CHAT_MODEL = "assistant";
public static final String KEY_NAME = "name";
public static final String KEY_EMAIL = "email";
public static final String KEY_MOBILE = "mobileNumber";
public static final String KEY_PASSWORD = "password";
public static final String KEY_PREFERENCE_NAME = "WhatsUpPreference";
public static final String KEY_IS_SIGNED_IN = "isSignedIn";
public static final String KEY_USER_ID = "userId";
public static final String KEY_FCM_TOKEN = "fcmToken";
public static final String KEY_USER_GENDER = "gender";
public static final String KEY_USER_DOB = "dob";
public static final String KEY_USER_AGE = "age";
public static final String KEY_COLLECTION_CHAT = "chat";
public static final String KEY_COLLECTION_MESSAGE = "messages";
public static final String KEY_SENDER_ID = "senderId";
public static final String KEY_RECEIVER_ID = "receiverId";
public static final String KEY_MESSAGE = "message";
public static final String KEY_IMAGE = "image";
public static final String KEY_TIMESTAMP = "timestamp";
public static final String KEY_PROFILE_IMAGE = "profilePicture";
public static final String KEY_COLLECTION_TREATMENTS = "treatments";
public static final String KEY_COLLECTION_MY_TREATMENTS = "myTreatments";
public static final String KEY_COLLECTION_SCHEDULES = "schedules";
public static final String KEY_COLLECTION_REPORT_ITEMS = "reportItems";
public static final String KEY_COLLECTION_SCHEDULED_ITEMS = "scheduledItems";
}
package com.HairDiary.utilities;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.ImageView;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class ImageUtilities {
public static byte[] getByteArrayFromUri(Uri uri, Activity activity){
byte[] imageByteArray = null;
// Open an InputStream from the URI
try (InputStream inputStream = activity.getContentResolver().openInputStream(uri)) {
if (inputStream != null) {
// Convert InputStream to byte array
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
imageByteArray = byteArrayOutputStream.toByteArray();
}
}catch (IOException e){
e.printStackTrace();
}
return imageByteArray;
}
}
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/input_background"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/primary_text" />
<size android:height="@dimen/_2sdp" />
<corners android:bottomLeftRadius="@dimen/_32sdp"
android:bottomRightRadius="@dimen/_32sdp"
android:topLeftRadius="@dimen/_32sdp"
android:topRightRadius="@dimen/_32sdp"/>
</shape>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment