├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── ic_launcher-playstore.png
│ │ ├── res
│ │ │ ├── font
│ │ │ │ ├── montserrat_medium.ttf
│ │ │ │ ├── montserrat_regular.ttf
│ │ │ │ └── montserrat_medium_italic.ttf
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── values
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ ├── strings.xml
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── themes.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── color
│ │ │ │ └── menu_item_color_state.xml
│ │ │ ├── xml
│ │ │ │ └── network_security_config.xml
│ │ │ ├── drawable
│ │ │ │ ├── ic_baseline_menu_24.xml
│ │ │ │ ├── ic_outline_clear_all_24.xml
│ │ │ │ ├── menu_item_background_color_state.xml
│ │ │ │ ├── ic_outline_complaint_2_24.xml
│ │ │ │ ├── ic_outline_email_24.xml
│ │ │ │ ├── background_round_padded_pressed.xml
│ │ │ │ ├── background_round_padded_selected.xml
│ │ │ │ ├── ic_outline_event_note_24.xml
│ │ │ │ ├── ic_outline_exit_to_app_24.xml
│ │ │ │ ├── ic_outline_create_24.xml
│ │ │ │ ├── ic_outline_house_24.xml
│ │ │ │ ├── ic_baseline_building_24.xml
│ │ │ │ ├── ic_outline_lock_24.xml
│ │ │ │ ├── ic_outline_qr_code_scanner_24.xml
│ │ │ │ ├── ic_outline_call_24.xml
│ │ │ │ ├── ic_outline_account_circle_24.xml
│ │ │ │ ├── ic_outline_local_phone_24.xml
│ │ │ │ ├── ic_outline_group_24.xml
│ │ │ │ └── ic_outline_directions_car_24.xml
│ │ │ ├── layout
│ │ │ │ ├── fragment_parking.xml
│ │ │ │ ├── fragment_home.xml
│ │ │ │ ├── item_event.xml
│ │ │ │ ├── item_meeting.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── item_emergency.xml
│ │ │ │ ├── bottom_nav_sheet.xml
│ │ │ │ ├── fragment_meetings.xml
│ │ │ │ ├── fragment_emergency.xml
│ │ │ │ ├── fragment_events.xml
│ │ │ │ ├── fragment_scanner.xml
│ │ │ │ ├── fragment_login.xml
│ │ │ │ └── fragment_register.xml
│ │ │ ├── menu
│ │ │ │ └── nav_menu.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── values-night-v29
│ │ │ │ └── themes.xml
│ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ ├── values-v29
│ │ │ │ └── themes.xml
│ │ │ └── navigation
│ │ │ │ └── nav_graph.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── kriticalflare
│ │ │ │ └── community
│ │ │ │ ├── util
│ │ │ │ ├── Constants.java
│ │ │ │ ├── AppExecutor.java
│ │ │ │ ├── Resource.java
│ │ │ │ └── NetworkBoundResource.java
│ │ │ │ ├── SocietyApp.java
│ │ │ │ ├── model
│ │ │ │ ├── LoginUser.java
│ │ │ │ ├── RegisterUser.java
│ │ │ │ └── LoginResponse.java
│ │ │ │ ├── di
│ │ │ │ ├── ExecutorModule.java
│ │ │ │ ├── PrefModule.java
│ │ │ │ ├── DatabaseModule.java
│ │ │ │ └── NetworkModule.java
│ │ │ │ ├── events
│ │ │ │ ├── data
│ │ │ │ │ ├── model
│ │ │ │ │ │ ├── EventsDao.java
│ │ │ │ │ │ ├── EventsResponse.java
│ │ │ │ │ │ └── Events.java
│ │ │ │ │ └── EventsRepository.java
│ │ │ │ ├── EventsViewHolder.java
│ │ │ │ ├── EventsViewModel.java
│ │ │ │ ├── EventsAdapter.java
│ │ │ │ └── EventsFragment.java
│ │ │ │ ├── meetings
│ │ │ │ ├── data
│ │ │ │ │ ├── model
│ │ │ │ │ │ ├── MeetingsResponse.java
│ │ │ │ │ │ ├── MeetingDao.java
│ │ │ │ │ │ └── Meeting.java
│ │ │ │ │ └── MeetingsRepository.java
│ │ │ │ └── ui
│ │ │ │ │ ├── MeetingViewHolder.java
│ │ │ │ │ ├── MeetingsViewModel.java
│ │ │ │ │ ├── MeetingsAdapter.java
│ │ │ │ │ └── MeetingsFragment.java
│ │ │ │ ├── parking
│ │ │ │ ├── data
│ │ │ │ │ ├── model
│ │ │ │ │ │ ├── ParkingBody.java
│ │ │ │ │ │ ├── GetParkingResponse.java
│ │ │ │ │ │ ├── ParkingResponse.java
│ │ │ │ │ │ ├── UserParkingItem.java
│ │ │ │ │ │ └── OtherParkingItem.java
│ │ │ │ │ └── ParkingRepository.java
│ │ │ │ └── ui
│ │ │ │ │ ├── ParkingViewModel.java
│ │ │ │ │ ├── ScannerViewModel.java
│ │ │ │ │ └── ScannerFragment.java
│ │ │ │ ├── emergency
│ │ │ │ ├── data
│ │ │ │ │ ├── model
│ │ │ │ │ │ ├── EmergencyDao.java
│ │ │ │ │ │ ├── EmergencyResponse.java
│ │ │ │ │ │ └── EmergencyItem.java
│ │ │ │ │ └── EmergencyRepository.java
│ │ │ │ └── ui
│ │ │ │ │ ├── EmergencyViewModel.java
│ │ │ │ │ ├── EmergencyViewHolder.java
│ │ │ │ │ ├── EmergencyAdapter.java
│ │ │ │ │ └── EmergencyFragment.java
│ │ │ │ ├── network
│ │ │ │ ├── AuthService.java
│ │ │ │ ├── ApiService.java
│ │ │ │ ├── AuthenticatedService.java
│ │ │ │ └── TokenInterceptor.java
│ │ │ │ ├── data
│ │ │ │ ├── local
│ │ │ │ │ ├── AppDatabase.java
│ │ │ │ │ └── PrefsDataStore.java
│ │ │ │ └── AuthenticationRepository.java
│ │ │ │ ├── AuthenticationViewModel.java
│ │ │ │ ├── home
│ │ │ │ └── HomeFragment.java
│ │ │ │ ├── register
│ │ │ │ └── RegisterFragment.java
│ │ │ │ └── login
│ │ │ │ └── LoginFragment.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── kriticalflare
│ │ │ └── community
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── kriticalflare
│ │ └── community
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── .idea
├── .gitignore
├── compiler.xml
├── vcs.xml
├── gradle.xml
└── misc.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/res/font/montserrat_medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/font/montserrat_medium.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/montserrat_regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/font/montserrat_regular.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/font/montserrat_medium_italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/font/montserrat_medium_italic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kriticalflare/SocietyApp/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #C41363
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/util/Constants.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.util;
2 |
3 | public class Constants {
4 | public static final String BASE_URL = "http://192.168.1.84:3001/api/";
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/SocietyApp.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community;
2 |
3 | import android.app.Application;
4 |
5 | import dagger.hilt.android.HiltAndroidApp;
6 |
7 | @HiltAndroidApp
8 | public class SocietyApp extends Application {
9 | }
10 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Sep 08 17:17:49 IST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/color/menu_item_color_state.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | /.idea/deploymentTargetDropDown.xml
3 | .gradle
4 | /local.properties
5 | /secrets.properties
6 | /.idea/caches
7 | /.idea/libraries
8 | /.idea/modules.xml
9 | /.idea/workspace.xml
10 | /.idea/navEditor.xml
11 | /.idea/assetWizardSettings.xml
12 | .DS_Store
13 | /build
14 | /captures
15 | .externalNativeBuild
16 | .cxx
17 | local.properties
18 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3 | repositories {
4 | google()
5 | mavenCentral()
6 | maven { url 'https://jitpack.io' }
7 | jcenter() // Warning: this repository is going to shut down soon
8 | }
9 | }
10 | rootProject.name = "Community"
11 | include ':app'
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 10.0.2.2
5 | 192.168.1.84
6 | localhost
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Community
3 |
4 | Hello blank fragment
5 | Please check your Internet Connection
6 | API ERROR
7 | Date: %1$s
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_menu_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_clear_all_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_item_background_color_state.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/model/LoginUser.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class LoginUser {
6 | @SerializedName("password")
7 | private String password;
8 |
9 | @SerializedName("email")
10 | public String email;
11 |
12 | public LoginUser(String email,String password) {
13 | this.email = email;
14 | this.password = password;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/test/java/com/kriticalflare/community/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/di/ExecutorModule.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.di;
2 |
3 | import com.kriticalflare.community.util.AppExecutor;
4 |
5 | import dagger.Module;
6 | import dagger.Provides;
7 | import dagger.hilt.InstallIn;
8 | import dagger.hilt.components.SingletonComponent;
9 |
10 | @Module
11 | @InstallIn(SingletonComponent.class)
12 | public class ExecutorModule {
13 | @Provides
14 | AppExecutor providesAppExecutor() {
15 | return new AppExecutor();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_complaint_2_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_email_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_round_padded_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
5 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/data/model/EventsDao.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events.data.model;
2 |
3 | import androidx.room.Dao;
4 | import androidx.room.Insert;
5 | import androidx.room.OnConflictStrategy;
6 | import androidx.room.Query;
7 |
8 | import java.util.List;
9 |
10 | @Dao
11 | public interface EventsDao {
12 |
13 | @Query("SELECT * FROM events")
14 | List getEvents();
15 |
16 | @Insert(onConflict = OnConflictStrategy.REPLACE)
17 | void insertEvents(List eventsList);
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_round_padded_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
5 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/data/model/MeetingsResponse.java:
--------------------------------------------------------------------------------
1 |
2 | package com.kriticalflare.community.meetings.data.model;
3 |
4 | import java.util.List;
5 | import com.google.gson.annotations.SerializedName;
6 |
7 | public class MeetingsResponse {
8 |
9 | @SerializedName("meetingsList")
10 | private List meeting;
11 |
12 | public List getMeetingsList() {
13 | return meeting;
14 | }
15 |
16 | public void setMeetingsList(List meeting) {
17 | this.meeting = meeting;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/data/model/ParkingBody.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.data.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class ParkingBody {
6 | @SerializedName("qrCode")
7 | private String qrCode;
8 |
9 | public ParkingBody(String qrCode){
10 | this.qrCode = qrCode;
11 | }
12 |
13 | public String getQrCode() {
14 | return qrCode;
15 | }
16 |
17 | public void setQrCode(String qrCode) {
18 | this.qrCode = qrCode;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_event_note_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/data/model/MeetingDao.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.meetings.data.model;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.room.Dao;
5 | import androidx.room.Insert;
6 | import androidx.room.OnConflictStrategy;
7 | import androidx.room.Query;
8 |
9 | import java.util.List;
10 |
11 | @Dao
12 | public interface MeetingDao {
13 | @Query("SELECT * FROM meetings")
14 | List getMeetings();
15 |
16 | @Insert(onConflict = OnConflictStrategy.REPLACE)
17 | void insertMeetings(List meetingList);
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/data/model/EmergencyDao.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.data.model;
2 |
3 | import androidx.room.Dao;
4 | import androidx.room.Insert;
5 | import androidx.room.OnConflictStrategy;
6 | import androidx.room.Query;
7 |
8 | import java.util.List;
9 |
10 | @Dao
11 | public interface EmergencyDao {
12 |
13 | @Insert(onConflict = OnConflictStrategy.REPLACE)
14 | public void insertEmergency(List emergencyItemList);
15 |
16 | @Query("SELECT * FROM emergencies")
17 | public List getEmergencies();
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/network/AuthService.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.network;
2 |
3 | import com.kriticalflare.community.model.LoginResponse;
4 | import com.kriticalflare.community.model.LoginUser;
5 | import com.kriticalflare.community.model.RegisterUser;
6 |
7 | import retrofit2.Call;
8 | import retrofit2.http.Body;
9 | import retrofit2.http.POST;
10 |
11 | public interface AuthService {
12 |
13 | @POST("register")
14 | Call registerUser(@Body RegisterUser user);
15 |
16 | @POST("login")
17 | Call login(@Body LoginUser user);
18 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_exit_to_app_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_create_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_house_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/data/model/GetParkingResponse.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.data.model;
2 |
3 | import java.util.List;
4 | import com.google.gson.annotations.SerializedName;
5 |
6 | public class GetParkingResponse{
7 |
8 | @SerializedName("userParking")
9 | private List userParking;
10 |
11 | @SerializedName("otherParking")
12 | private List otherParking;
13 |
14 | public List getUserParking(){
15 | return userParking;
16 | }
17 |
18 | public List getOtherParking(){
19 | return otherParking;
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_building_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_lock_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/data/model/EventsResponse.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events.data.model;
2 |
3 | import java.util.List;
4 | import com.google.gson.annotations.SerializedName;
5 |
6 | public class EventsResponse{
7 |
8 | @SerializedName("eventList")
9 | private List eventList;
10 |
11 | public void setEventList(List eventList){
12 | this.eventList = eventList;
13 | }
14 |
15 | public List getEventList(){
16 | return eventList;
17 | }
18 |
19 | @Override
20 | public String toString(){
21 | return
22 | "EventsResponse{" +
23 | "eventList = '" + eventList + '\'' +
24 | "}";
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/network/ApiService.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.network;
2 |
3 | import com.kriticalflare.community.emergency.data.model.EmergencyResponse;
4 | import com.kriticalflare.community.events.data.model.EventsResponse;
5 | import com.kriticalflare.community.meetings.data.model.MeetingsResponse;
6 |
7 | import retrofit2.Call;
8 | import retrofit2.http.GET;
9 |
10 | public interface ApiService {
11 |
12 | @GET("meeting")
13 | Call getMeetings();
14 |
15 | @GET("emergency_number")
16 | Call getEmergencies();
17 |
18 | @GET("events")
19 | Call getEvents();
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/data/model/ParkingResponse.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.data.model;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.google.gson.annotations.SerializedName;
6 |
7 | public class ParkingResponse{
8 |
9 | @SerializedName("isParked")
10 | private boolean isParked;
11 |
12 | @SerializedName("message")
13 | private String message;
14 |
15 | public boolean isParked(){
16 | return isParked;
17 | }
18 |
19 | public String getMessage(){
20 | return message;
21 | }
22 |
23 | @NonNull
24 | @Override
25 | public String toString(){
26 | return
27 | "ParkingResponse{" +
28 | "isParked = '" + isParked + '\'' +
29 | ",message = '" + message + '\'' +
30 | "}";
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_qr_code_scanner_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/data/model/EmergencyResponse.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.data.model;
2 |
3 | import java.util.List;
4 | import com.google.gson.annotations.SerializedName;
5 |
6 | public class EmergencyResponse {
7 |
8 | @SerializedName("emergencyNumberList")
9 | private List emergencyNumberList;
10 |
11 | public void setEmergencyNumberList(List emergencyNumberList){
12 | this.emergencyNumberList = emergencyNumberList;
13 | }
14 |
15 | public List getEmergencyNumberList(){
16 | return emergencyNumberList;
17 | }
18 |
19 | @Override
20 | public String toString(){
21 | return
22 | "Response{" +
23 | "emergencyNumberList = '" + emergencyNumberList + '\'' +
24 | "}";
25 | }
26 | }
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/EventsViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events;
2 |
3 | import android.view.View;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.recyclerview.widget.RecyclerView;
7 |
8 | import com.kriticalflare.community.databinding.ItemEventBinding;
9 | import com.kriticalflare.community.events.data.model.Events;
10 |
11 | public class EventsViewHolder extends RecyclerView.ViewHolder {
12 | public EventsViewHolder(@NonNull View itemView) {
13 | super(itemView);
14 | binding = ItemEventBinding.bind(itemView);
15 | }
16 |
17 | private ItemEventBinding binding;
18 |
19 | public void bind(Events data) {
20 | binding.eventAgenda.setText(data.getAgenda());
21 | binding.eventDate.setText(data.getTime());
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/data/model/UserParkingItem.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.data.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class UserParkingItem{
6 |
7 | @SerializedName("User")
8 | private String user;
9 |
10 | @SerializedName("qrCode")
11 | private String qrCode;
12 |
13 | @SerializedName("Long")
14 | private String longitude;
15 |
16 | @SerializedName("_id")
17 | private String id;
18 |
19 | @SerializedName("Lat")
20 | private String latitude;
21 |
22 | public String getUser(){
23 | return user;
24 | }
25 |
26 | public String getQrCode(){
27 | return qrCode;
28 | }
29 |
30 | public String getLongitude(){
31 | return longitude;
32 | }
33 |
34 | public String getId(){
35 | return id;
36 | }
37 |
38 | public String getLatitude(){
39 | return latitude;
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/data/model/OtherParkingItem.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.data.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class OtherParkingItem{
6 |
7 | @SerializedName("User")
8 | private String user;
9 |
10 | @SerializedName("qrCode")
11 | private String qrCode;
12 |
13 | @SerializedName("Long")
14 | private String longitude;
15 |
16 | @SerializedName("_id")
17 | private String id;
18 |
19 | @SerializedName("Lat")
20 | private String latitude;
21 |
22 | public String getUser(){
23 | return user;
24 | }
25 |
26 | public String getQrCode(){
27 | return qrCode;
28 | }
29 |
30 | public String getLongitude(){
31 | return longitude;
32 | }
33 |
34 | public String getId(){
35 | return id;
36 | }
37 |
38 | public String getLatitude(){
39 | return latitude;
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/ui/ParkingViewModel.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.ui;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.ViewModel;
5 |
6 | import com.kriticalflare.community.parking.data.ParkingRepository;
7 | import com.kriticalflare.community.parking.data.model.GetParkingResponse;
8 | import com.kriticalflare.community.util.Resource;
9 |
10 | import javax.inject.Inject;
11 |
12 | import dagger.hilt.android.lifecycle.HiltViewModel;
13 |
14 | @HiltViewModel
15 | public class ParkingViewModel extends ViewModel {
16 |
17 | private ParkingRepository repo;
18 |
19 | @Inject
20 | ParkingViewModel(ParkingRepository repo){
21 | this.repo = repo;
22 | }
23 |
24 | public LiveData> getParkingSpots(){
25 | return repo.getParkingSpots();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_call_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_account_circle_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_local_phone_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/di/PrefModule.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.di;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.datastore.preferences.core.Preferences;
6 | import androidx.datastore.preferences.rxjava3.RxPreferenceDataStoreBuilder;
7 | import androidx.datastore.rxjava3.RxDataStore;
8 |
9 | import javax.inject.Singleton;
10 |
11 | import dagger.Module;
12 | import dagger.Provides;
13 | import dagger.hilt.InstallIn;
14 | import dagger.hilt.android.qualifiers.ApplicationContext;
15 | import dagger.hilt.components.SingletonComponent;
16 |
17 | @Module
18 | @InstallIn(SingletonComponent.class)
19 | public class PrefModule {
20 | @Singleton
21 | @Provides
22 | public RxDataStore provideDataStore(@ApplicationContext Context context) {
23 | return new RxPreferenceDataStoreBuilder(context, "prefs").build();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_group_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_directions_car_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/network/AuthenticatedService.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.network;
2 |
3 | import com.kriticalflare.community.parking.data.model.GetParkingResponse;
4 | import com.kriticalflare.community.parking.data.model.ParkingBody;
5 | import com.kriticalflare.community.parking.data.model.ParkingResponse;
6 |
7 | import retrofit2.Call;
8 | import retrofit2.http.Body;
9 | import retrofit2.http.DELETE;
10 | import retrofit2.http.GET;
11 | import retrofit2.http.HTTP;
12 | import retrofit2.http.POST;
13 |
14 | public interface AuthenticatedService {
15 |
16 | @GET("parking")
17 | Call getParkingSpots();
18 |
19 | @POST("parking")
20 | Call claimParkingSpot(@Body ParkingBody parkingBody);
21 |
22 | @HTTP(method = "DELETE", path = "parking", hasBody = true)
23 | Call clearParkingSpot(@Body ParkingBody parkingBody);
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/kriticalflare/community/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.kriticalflare.community", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/data/local/AppDatabase.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.data.local;
2 |
3 | import androidx.room.Database;
4 | import androidx.room.RoomDatabase;
5 |
6 | import com.kriticalflare.community.emergency.data.model.EmergencyDao;
7 | import com.kriticalflare.community.emergency.data.model.EmergencyItem;
8 | import com.kriticalflare.community.events.data.model.Events;
9 | import com.kriticalflare.community.events.data.model.EventsDao;
10 | import com.kriticalflare.community.meetings.data.model.Meeting;
11 | import com.kriticalflare.community.meetings.data.model.MeetingDao;
12 |
13 | @Database(entities = {Meeting.class, EmergencyItem.class, Events.class}, version = 1, exportSchema = false)
14 | public abstract class AppDatabase extends RoomDatabase {
15 | public abstract MeetingDao meetingDao();
16 | public abstract EmergencyDao emergencyDao();
17 | public abstract EventsDao eventsDao();
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/ui/MeetingViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.meetings.ui;
2 |
3 | import android.view.View;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.recyclerview.widget.RecyclerView;
7 |
8 | import com.kriticalflare.community.R;
9 | import com.kriticalflare.community.databinding.ItemMeetingBinding;
10 | import com.kriticalflare.community.meetings.data.model.Meeting;
11 |
12 | public class MeetingViewHolder extends RecyclerView.ViewHolder {
13 | private ItemMeetingBinding binding;
14 |
15 | public MeetingViewHolder(@NonNull View itemView) {
16 | super(itemView);
17 | binding = ItemMeetingBinding.bind(itemView);
18 | }
19 |
20 | public void bind(Meeting meeting) {
21 | binding.meetingAgenda.setText(meeting.getAgenda());
22 | binding.meetingDate.setText(itemView.getContext().getString(R.string.date_representation, meeting.getTime()));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/ui/MeetingsViewModel.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.meetings.ui;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.ViewModel;
5 |
6 | import com.kriticalflare.community.meetings.data.MeetingsRepository;
7 | import com.kriticalflare.community.meetings.data.model.Meeting;
8 | import com.kriticalflare.community.util.Resource;
9 |
10 | import java.util.List;
11 |
12 | import javax.inject.Inject;
13 |
14 | import dagger.hilt.android.lifecycle.HiltViewModel;
15 |
16 | @HiltViewModel
17 | public class MeetingsViewModel extends ViewModel {
18 | private MeetingsRepository repo;
19 | public LiveData>> meetings;
20 |
21 | @Inject
22 | public MeetingsViewModel(MeetingsRepository repo) {
23 | this.repo = repo;
24 | meetings = repo.getMeetings();
25 | }
26 |
27 | public void refreshMeetings(){
28 | repo.refreshMeetings();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/ui/ScannerViewModel.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.ui;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.ViewModel;
5 |
6 | import com.kriticalflare.community.parking.data.ParkingRepository;
7 | import com.kriticalflare.community.parking.data.model.ParkingResponse;
8 | import com.kriticalflare.community.util.Resource;
9 |
10 | import javax.inject.Inject;
11 |
12 | import dagger.hilt.android.lifecycle.HiltViewModel;
13 |
14 | @HiltViewModel
15 | public class ScannerViewModel extends ViewModel {
16 |
17 | private ParkingRepository repo;
18 |
19 | @Inject
20 | ScannerViewModel(ParkingRepository repo){
21 | this.repo = repo;
22 | }
23 |
24 | public LiveData> claimParkingSpot(String qrCode){
25 | return repo.claimParkingSpots(qrCode);
26 | }
27 |
28 | public LiveData> clearParkingSpot(String qrCode){
29 | return repo.clearParkingSpot(qrCode);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/ui/EmergencyViewModel.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.ui;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.ViewModel;
5 |
6 | import com.kriticalflare.community.emergency.data.EmergencyRepository;
7 | import com.kriticalflare.community.emergency.data.model.EmergencyItem;
8 | import com.kriticalflare.community.util.Resource;
9 |
10 | import java.util.List;
11 |
12 | import javax.inject.Inject;
13 |
14 | import dagger.hilt.android.lifecycle.HiltViewModel;
15 |
16 | @HiltViewModel
17 | public class EmergencyViewModel extends ViewModel {
18 |
19 | private EmergencyRepository repo;
20 |
21 | @Inject
22 | public EmergencyViewModel(EmergencyRepository emergencyRepository) {
23 | this.repo = emergencyRepository;
24 | }
25 |
26 | public LiveData>> getEmergencies(){
27 | return repo.getEmergencies();
28 | }
29 |
30 | public void refreshEmergencies(){
31 | repo.refreshEmergencies();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/model/RegisterUser.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.model;
2 | /*
3 | {
4 | "name": "krithik",
5 | "room_number": "10",
6 | "buil_number": "e3",
7 | "password": "12345689",
8 | "email": "krithiksuvarna@gmail.com"
9 | }
10 | */
11 |
12 | import com.google.gson.annotations.SerializedName;
13 |
14 | public class RegisterUser {
15 | @SerializedName("name")
16 | private String name;
17 |
18 | @SerializedName("room_number")
19 | private String roomNumber;
20 |
21 | @SerializedName("building_number")
22 | private String buildingNumber;
23 |
24 | @SerializedName("password")
25 | private String password;
26 |
27 | @SerializedName("email")
28 | private String email;
29 |
30 | public RegisterUser(String name, String email, String password, String roomNumber, String buildingNumber) {
31 | this.name = name;
32 | this.email = email;
33 | this.password = password;
34 | this.roomNumber = roomNumber;
35 | this.buildingNumber = buildingNumber;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/EventsViewModel.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.ViewModel;
5 |
6 | import com.kriticalflare.community.emergency.data.EmergencyRepository;
7 | import com.kriticalflare.community.emergency.data.model.EmergencyItem;
8 | import com.kriticalflare.community.events.data.EventsRepository;
9 | import com.kriticalflare.community.events.data.model.Events;
10 | import com.kriticalflare.community.util.Resource;
11 |
12 | import java.util.List;
13 |
14 | import javax.inject.Inject;
15 |
16 | import dagger.hilt.android.lifecycle.HiltViewModel;
17 |
18 | @HiltViewModel
19 | public class EventsViewModel extends ViewModel {
20 | private EventsRepository repo;
21 |
22 | @Inject
23 | public EventsViewModel(EventsRepository eventsRepository) {
24 | this.repo = eventsRepository;
25 | }
26 |
27 | public LiveData>> getEvents(){
28 | return repo.getEvents();
29 | }
30 |
31 | public void refreshEvents(){
32 | repo.refreshEvents();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/network/TokenInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.network;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.kriticalflare.community.data.AuthenticationRepository;
6 | import com.kriticalflare.community.data.local.PrefsDataStore;
7 |
8 | import java.io.IOException;
9 |
10 | import javax.inject.Inject;
11 |
12 | import okhttp3.Interceptor;
13 | import okhttp3.Request;
14 | import okhttp3.Response;
15 |
16 | public class TokenInterceptor implements Interceptor {
17 |
18 | private PrefsDataStore dataStore;
19 |
20 | @Inject
21 | public TokenInterceptor(PrefsDataStore dataStore){
22 | this.dataStore = dataStore;
23 | }
24 |
25 | @NonNull
26 | @Override
27 | public Response intercept(@NonNull Chain chain) throws IOException {
28 | Request originalRequest = chain.request();
29 | String token = dataStore.getJWTToken().blockingFirst();
30 | Request.Builder newRequest = originalRequest
31 | .newBuilder()
32 | .addHeader("x-access-token", token);
33 | return chain.proceed(newRequest.build());
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 | #146F80
11 | #C41363
12 | #fc5590
13 | #8e0039
14 | #c8bd6f
15 | #86c2e7
16 | #5b5fd4
17 | #20364c
18 | #202124
19 | #2E2F32
20 | #e8e9ec
21 | #e49085
22 | #594645
23 | #606367
24 | #3d4043
25 | #B3666666
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/ui/EmergencyViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.ui;
2 |
3 | import android.content.Intent;
4 | import android.net.Uri;
5 | import android.view.View;
6 |
7 | import androidx.recyclerview.widget.RecyclerView;
8 |
9 | import com.kriticalflare.community.databinding.ItemEmergencyBinding;
10 | import com.kriticalflare.community.emergency.data.model.EmergencyItem;
11 |
12 | public class EmergencyViewHolder extends RecyclerView.ViewHolder {
13 |
14 | private ItemEmergencyBinding binding;
15 |
16 | public EmergencyViewHolder(View itemView) {
17 | super(itemView);
18 | binding = ItemEmergencyBinding.bind(itemView);
19 | }
20 |
21 | public void bind(EmergencyItem data) {
22 | binding.emergencyNumber.setText(data.getNumber());
23 | binding.emergencyTitle.setText(data.getJobTitle());
24 | binding.callButton.setOnClickListener(view -> {
25 | Intent intent = new Intent(Intent.ACTION_DIAL);
26 | intent.setData(Uri.parse("tel:" + data.getNumber()));
27 | if (intent.resolveActivity(binding.getRoot().getContext().getPackageManager()) != null) {
28 | binding.getRoot().getContext().startActivity(intent);
29 | }
30 |
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/model/LoginResponse.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.model;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.google.gson.annotations.SerializedName;
6 |
7 | public class LoginResponse{
8 |
9 | @SerializedName("password")
10 | private String password;
11 |
12 | @SerializedName("__v")
13 | private int V;
14 |
15 | @SerializedName("name")
16 | private String name;
17 |
18 | @SerializedName("room_number")
19 | private String roomNumber;
20 |
21 | @SerializedName("_id")
22 | private String id;
23 |
24 | @SerializedName("building_number")
25 | private String buildingNumber;
26 |
27 | @SerializedName("email")
28 | private String email;
29 |
30 | @SerializedName("token")
31 | private String token;
32 |
33 | public String getPassword(){
34 | return password;
35 | }
36 |
37 | public int getV(){
38 | return V;
39 | }
40 |
41 | public String getName(){
42 | return name;
43 | }
44 |
45 | public String getRoomNumber(){
46 | return roomNumber;
47 | }
48 |
49 | public String getId(){
50 | return id;
51 | }
52 |
53 | public String getBuildingNumber(){
54 | return buildingNumber;
55 | }
56 |
57 | public String getEmail(){
58 | return email;
59 | }
60 |
61 | @NonNull
62 | public String getToken(){
63 | return token;
64 | }
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/util/AppExecutor.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.util;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | import java.util.concurrent.Executor;
9 | import java.util.concurrent.Executors;
10 |
11 | public class AppExecutor {
12 |
13 | private Executor diskIO;
14 | private final Executor mainThread;
15 | private Executor networkIO;
16 |
17 | private AppExecutor(Executor diskIO, Executor networkIO, Executor mainThread) {
18 | this.diskIO = diskIO;
19 | this.networkIO = networkIO;
20 | this.mainThread = mainThread;
21 | }
22 |
23 | public AppExecutor() {
24 | this(Executors.newSingleThreadExecutor(),
25 | Executors.newFixedThreadPool(3),
26 | new MainThreadExecutor());
27 | }
28 |
29 | public Executor diskIO() {
30 | return diskIO;
31 | }
32 |
33 | public Executor networkIO() {
34 | return networkIO;
35 | }
36 |
37 | public Executor mainThread() {
38 | return mainThread;
39 | }
40 |
41 | private static class MainThreadExecutor implements Executor {
42 | private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
43 |
44 | @Override
45 | public void execute(@NonNull Runnable command) {
46 | mainThreadHandler.post(command);
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_parking.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/nav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/di/DatabaseModule.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.di;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.room.Room;
6 |
7 | import com.kriticalflare.community.data.local.AppDatabase;
8 | import com.kriticalflare.community.emergency.data.model.EmergencyDao;
9 | import com.kriticalflare.community.events.data.model.EventsDao;
10 | import com.kriticalflare.community.meetings.data.model.MeetingDao;
11 |
12 | import javax.inject.Singleton;
13 |
14 | import dagger.Module;
15 | import dagger.Provides;
16 | import dagger.hilt.InstallIn;
17 | import dagger.hilt.android.qualifiers.ApplicationContext;
18 | import dagger.hilt.components.SingletonComponent;
19 |
20 | @Module
21 | @InstallIn(SingletonComponent.class)
22 | public class DatabaseModule {
23 |
24 | @Singleton
25 | @Provides
26 | AppDatabase providesAppDatabase(@ApplicationContext Context context) {
27 | return Room
28 | .databaseBuilder(context, AppDatabase.class, "SocietyDatabase")
29 | .fallbackToDestructiveMigration().build();
30 | }
31 |
32 | @Provides
33 | MeetingDao providesMeetingDao(AppDatabase database) {
34 | return database.meetingDao();
35 | }
36 |
37 | @Provides
38 | EmergencyDao providesEmergencyDao(AppDatabase database) {
39 | return database.emergencyDao();
40 | }
41 |
42 | @Provides
43 | EventsDao providesEventsDao(AppDatabase database) {
44 | return database.eventsDao();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/AuthenticationViewModel.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.ViewModel;
5 |
6 | import com.kriticalflare.community.data.AuthenticationRepository;
7 | import com.kriticalflare.community.model.LoginUser;
8 | import com.kriticalflare.community.model.RegisterUser;
9 | import com.zhuinden.eventemitter.EventSource;
10 |
11 | import javax.inject.Inject;
12 |
13 | import dagger.hilt.android.lifecycle.HiltViewModel;
14 | import io.reactivex.rxjava3.core.Flowable;
15 |
16 | @HiltViewModel
17 | public class AuthenticationViewModel extends ViewModel {
18 | private final AuthenticationRepository authRepo;
19 | public LiveData loading;
20 | public final EventSource eventMessages;
21 |
22 | @Inject
23 | AuthenticationViewModel(AuthenticationRepository authRepo) {
24 | this.authRepo = authRepo;
25 | this.eventMessages = authRepo.errorEvents;
26 | this.loading = authRepo.loading;
27 | }
28 |
29 | public void register(RegisterUser user){
30 | authRepo.register(user);
31 | }
32 |
33 | public void login(LoginUser user){
34 | authRepo.login(user);
35 | }
36 |
37 | public void logout(){
38 | authRepo.logout();
39 | }
40 |
41 | public Flowable isLoggedIn() {
42 | return authRepo.getLoginStatus();
43 | }
44 |
45 | public void setLoggedIn(boolean status) {
46 | authRepo.saveLoginStatus(status);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
16 |
24 |
32 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/util/Resource.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.util;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import androidx.annotation.StringRes;
6 |
7 | import com.kriticalflare.community.R;
8 |
9 | public class Resource {
10 |
11 | @NonNull
12 | public final Status status;
13 | @Nullable
14 | public final T data;
15 | @Nullable
16 | @StringRes
17 | public final Integer message;
18 | @Nullable
19 | public final String apiMessage;
20 |
21 | private Resource(@NonNull Status status, @Nullable T data, @Nullable Integer message, @Nullable String apiMessage) {
22 | this.status = status;
23 | this.data = data;
24 | this.message = message;
25 | this.apiMessage = apiMessage;
26 | }
27 |
28 | public static Resource success(@NonNull T data) {
29 | return new Resource<>(Status.SUCCESS, data, null, null);
30 | }
31 |
32 | public static Resource error(@Nullable T data, String apiMessage) {
33 | return new Resource<>(Status.ERROR, data, R.string.api_error_message, apiMessage);
34 | }
35 |
36 | public static Resource loading(@Nullable T data) {
37 | return new Resource<>(Status.LOADING, data, null, null);
38 | }
39 |
40 | public static Resource noNetwork(@Nullable T data) {
41 | return new Resource<>(Status.NO_NETWORK, data, R.string.network_issue_message, null);
42 | }
43 |
44 | public enum Status {
45 | SUCCESS, ERROR, LOADING, NO_NETWORK
46 | }
47 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
25 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/data/model/EmergencyItem.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.data.model;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.room.Entity;
5 | import androidx.room.PrimaryKey;
6 |
7 | import com.google.gson.annotations.SerializedName;
8 |
9 | @Entity(tableName = "emergencies")
10 | public class EmergencyItem{
11 |
12 | @SerializedName("number")
13 | private String number;
14 |
15 | @SerializedName("name")
16 | private String name;
17 |
18 | @PrimaryKey
19 | @NonNull
20 | @SerializedName("_id")
21 | private String id;
22 |
23 | @SerializedName("Job_title")
24 | private String jobTitle;
25 |
26 | public void setNumber(String number){
27 | this.number = number;
28 | }
29 |
30 | public String getNumber(){
31 | return number;
32 | }
33 |
34 | public void setName(String name){
35 | this.name = name;
36 | }
37 |
38 | public String getName(){
39 | return name;
40 | }
41 |
42 | public void setId(String id){
43 | this.id = id;
44 | }
45 |
46 | public String getId(){
47 | return id;
48 | }
49 |
50 | public void setJobTitle(String jobTitle){
51 | this.jobTitle = jobTitle;
52 | }
53 |
54 | public String getJobTitle(){
55 | return jobTitle;
56 | }
57 |
58 | public EmergencyItem(String number, String name, @NonNull String id, String jobTitle) {
59 | this.number = number;
60 | this.name = name;
61 | this.id = id;
62 | this.jobTitle = jobTitle;
63 | }
64 |
65 | @Override
66 | public String toString(){
67 | return
68 | "EmergencyNumberListItem{" +
69 | "number = '" + number + '\'' +
70 | ",name = '" + name + '\'' +
71 | ",_id = '" + id + '\'' +
72 | ",job_title = '" + jobTitle + '\'' +
73 | "}";
74 | }
75 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/data/model/Meeting.java:
--------------------------------------------------------------------------------
1 |
2 | package com.kriticalflare.community.meetings.data.model;
3 |
4 | import androidx.annotation.NonNull;
5 | import androidx.room.Entity;
6 | import androidx.room.PrimaryKey;
7 |
8 | import com.google.gson.annotations.SerializedName;
9 |
10 | @Entity(tableName = "meetings")
11 | public class Meeting {
12 | public Meeting(@NonNull String _id, String agenda, String description, String time, String title) {
13 | this._id = _id;
14 | this.agenda = agenda;
15 | this.description = description;
16 | this.time = time;
17 | this.title = title;
18 | }
19 |
20 | @PrimaryKey
21 | @SerializedName("_id")
22 | @NonNull
23 | private String _id;
24 | @SerializedName("agenda")
25 | private String agenda;
26 | @SerializedName("description")
27 | private String description;
28 | @SerializedName("time")
29 | private String time;
30 | @SerializedName("title")
31 | private String title;
32 |
33 | public String get_id() {
34 | return _id;
35 | }
36 |
37 | public void set_id(String _id) {
38 | this._id = _id;
39 | }
40 |
41 | public String getAgenda() {
42 | return agenda;
43 | }
44 |
45 | public void setAgenda(String agenda) {
46 | this.agenda = agenda;
47 | }
48 |
49 | public String getDescription() {
50 | return description;
51 | }
52 |
53 | public void setDescription(String description) {
54 | this.description = description;
55 | }
56 |
57 | public String getTime() {
58 | return time;
59 | }
60 |
61 | public void setTime(String time) {
62 | this.time = time;
63 | }
64 |
65 | public String getTitle() {
66 | return title;
67 | }
68 |
69 | public void setTitle(String title) {
70 | this.title = title;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_event.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
14 |
25 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_meeting.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
14 |
25 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
24 |
25 |
36 |
37 |
38 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/EventsAdapter.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.ViewGroup;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.recyclerview.widget.DiffUtil;
8 | import androidx.recyclerview.widget.ListAdapter;
9 |
10 | import com.kriticalflare.community.databinding.ItemEventBinding;
11 | import com.kriticalflare.community.events.data.model.Events;
12 |
13 | public class EventsAdapter extends ListAdapter {
14 | protected EventsAdapter() {
15 | super(EventsAdapter.DIFF_CALLBACK);
16 | }
17 |
18 | private ItemEventBinding binding;
19 |
20 | @NonNull
21 | @Override
22 | public EventsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
23 | binding = ItemEventBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
24 | return new EventsViewHolder(binding.getRoot());
25 | }
26 |
27 | @Override
28 | public void onBindViewHolder(@NonNull EventsViewHolder holder, int position) {
29 | holder.bind(getItem(position));
30 | }
31 |
32 | public static final DiffUtil.ItemCallback DIFF_CALLBACK =
33 | new DiffUtil.ItemCallback() {
34 |
35 | @Override
36 | public boolean areItemsTheSame(@NonNull Events oldItem, @NonNull Events newItem) {
37 | return oldItem.getId().equals(newItem.getId());
38 | }
39 |
40 | @Override
41 | public boolean areContentsTheSame(
42 | @NonNull Events oldItem, @NonNull Events newItem) {
43 | // NOTE: if you use equals, your object must properly override Object#equals()
44 | // Incorrectly returning false here will result in too many animations.
45 | return oldItem.getId().equals(newItem.getId());
46 | }
47 | };
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/ui/MeetingsAdapter.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.meetings.ui;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.ViewGroup;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.recyclerview.widget.DiffUtil;
8 | import androidx.recyclerview.widget.ListAdapter;
9 |
10 | import com.kriticalflare.community.databinding.ItemMeetingBinding;
11 | import com.kriticalflare.community.meetings.data.model.Meeting;
12 |
13 | public class MeetingsAdapter extends ListAdapter {
14 | private ItemMeetingBinding binding;
15 |
16 | MeetingsAdapter() {
17 | super(MeetingsAdapter.DIFF_CALLBACK);
18 | }
19 |
20 | @NonNull
21 | @Override
22 | public MeetingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
23 | binding = ItemMeetingBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
24 | return new MeetingViewHolder(binding.getRoot());
25 | }
26 |
27 |
28 | @Override
29 | public void onBindViewHolder(@NonNull MeetingViewHolder holder, int position) {
30 | holder.bind(getCurrentList().get(position));
31 | }
32 |
33 | public static final DiffUtil.ItemCallback DIFF_CALLBACK =
34 | new DiffUtil.ItemCallback() {
35 |
36 | @Override
37 | public boolean areItemsTheSame(@NonNull Meeting oldItem, @NonNull Meeting newItem) {
38 | return oldItem.get_id().equals(newItem.get_id());
39 | }
40 |
41 | @Override
42 | public boolean areContentsTheSame(
43 | @NonNull Meeting oldItem, @NonNull Meeting newItem) {
44 | // NOTE: if you use equals, your object must properly override Object#equals()
45 | // Incorrectly returning false here will result in too many animations.
46 | return oldItem.get_id().equals(newItem.get_id());
47 | }
48 | };
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/ui/EmergencyAdapter.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.ui;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.ViewGroup;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.recyclerview.widget.DiffUtil;
8 | import androidx.recyclerview.widget.ListAdapter;
9 |
10 | import com.kriticalflare.community.databinding.ItemEmergencyBinding;
11 | import com.kriticalflare.community.emergency.data.model.EmergencyItem;
12 |
13 | public class EmergencyAdapter extends ListAdapter {
14 |
15 | private ItemEmergencyBinding binding;
16 |
17 | EmergencyAdapter() {
18 | super(EmergencyAdapter.DIFF_CALLBACK);
19 | }
20 |
21 | @NonNull
22 | @Override
23 | public EmergencyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
24 | binding = ItemEmergencyBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
25 | return new EmergencyViewHolder(binding.getRoot());
26 | }
27 |
28 | @Override
29 | public void onBindViewHolder(@NonNull EmergencyViewHolder holder, int position) {
30 | holder.bind(getCurrentList().get(position));
31 | }
32 |
33 | public static final DiffUtil.ItemCallback DIFF_CALLBACK =
34 | new DiffUtil.ItemCallback() {
35 |
36 | @Override
37 | public boolean areItemsTheSame(@NonNull EmergencyItem oldItem, @NonNull EmergencyItem newItem) {
38 | return oldItem.getId().equals(newItem.getId());
39 | }
40 |
41 | @Override
42 | public boolean areContentsTheSame(
43 | @NonNull EmergencyItem oldItem, @NonNull EmergencyItem newItem) {
44 | // NOTE: if you use equals, your object must properly override Object#equals()
45 | // Incorrectly returning false here will result in too many animations.
46 | return oldItem.getId().equals(newItem.getId());
47 | }
48 | };
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/data/local/PrefsDataStore.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.data.local;
2 |
3 | import androidx.datastore.preferences.core.MutablePreferences;
4 | import androidx.datastore.preferences.core.Preferences;
5 | import androidx.datastore.preferences.core.PreferencesKeys;
6 | import androidx.datastore.rxjava3.RxDataStore;
7 |
8 | import java.util.Optional;
9 |
10 | import javax.inject.Inject;
11 |
12 | import io.reactivex.rxjava3.core.Flowable;
13 | import io.reactivex.rxjava3.core.Single;
14 |
15 | public class PrefsDataStore {
16 | public final RxDataStore dataStore;
17 |
18 | @Inject
19 | PrefsDataStore(RxDataStore dataStore){
20 | this.dataStore = dataStore;
21 | }
22 | public void saveEmail(String email) {
23 | dataStore.updateDataAsync(preferences -> {
24 | MutablePreferences _prefs = preferences.toMutablePreferences();
25 | _prefs.set(KEY_EMAIL, email);
26 | return Single.just(_prefs);
27 | });
28 | }
29 | public void saveLoginStatus(boolean status) {
30 | dataStore.updateDataAsync(preferences -> {
31 | MutablePreferences _prefs = preferences.toMutablePreferences();
32 | _prefs.set(KEY_IS_LOGGED_IN, status);
33 | return Single.just(_prefs);
34 | });
35 | }
36 |
37 | public void saveToken(String token) {
38 | dataStore.updateDataAsync(preferences -> {
39 | MutablePreferences _prefs = preferences.toMutablePreferences();
40 | _prefs.set(KEY_JWT, token);
41 | return Single.just(_prefs);
42 | });
43 | }
44 |
45 |
46 | public Flowable getLoginStatus() {
47 | return dataStore.data().map(preferences -> Optional.ofNullable(preferences.get(KEY_IS_LOGGED_IN)).orElse(false));
48 | }
49 |
50 | public Flowable getJWTToken() {
51 | return dataStore.data().map(preferences -> preferences.get(KEY_JWT));
52 | }
53 | public static final Preferences.Key KEY_EMAIL = PreferencesKeys.stringKey("key_email");
54 | public static final Preferences.Key KEY_IS_LOGGED_IN =
55 | PreferencesKeys.booleanKey("key_is_logged_in");
56 | public static final Preferences.Key KEY_JWT = PreferencesKeys.stringKey("token");
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/data/model/Events.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events.data.model;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.room.Entity;
5 | import androidx.room.PrimaryKey;
6 |
7 | import com.google.gson.annotations.SerializedName;
8 |
9 | @Entity(tableName = "events")
10 | public class Events {
11 |
12 | @SerializedName("description")
13 | private String description;
14 |
15 | @PrimaryKey
16 | @NonNull
17 | @SerializedName("_id")
18 | private String id;
19 |
20 | @SerializedName("time")
21 | private String time;
22 |
23 | @SerializedName("title")
24 | private String title;
25 |
26 | @SerializedName("agenda")
27 | private String agenda;
28 |
29 | public Events(String description, @NonNull String id, String time, String title, String agenda) {
30 | this.description = description;
31 | this.id = id;
32 | this.time = time;
33 | this.title = title;
34 | this.agenda = agenda;
35 | }
36 |
37 | public void setDescription(String description) {
38 | this.description = description;
39 | }
40 |
41 | public String getDescription() {
42 | return description;
43 | }
44 |
45 | public void setId(String id) {
46 | this.id = id;
47 | }
48 |
49 | public String getId() {
50 | return id;
51 | }
52 |
53 | public void setTime(String time) {
54 | this.time = time;
55 | }
56 |
57 | public String getTime() {
58 | return time;
59 | }
60 |
61 | public void setTitle(String title) {
62 | this.title = title;
63 | }
64 |
65 | public String getTitle() {
66 | return title;
67 | }
68 |
69 | public void setAgenda(String agenda) {
70 | this.agenda = agenda;
71 | }
72 |
73 | public String getAgenda() {
74 | return agenda;
75 | }
76 |
77 | @Override
78 | public String toString() {
79 | return
80 | "EventListItem{" +
81 | "description = '" + description + '\'' +
82 | ",_id = '" + id + '\'' +
83 | ",time = '" + time + '\'' +
84 | ",title = '" + title + '\'' +
85 | ",agenda = '" + agenda + '\'' +
86 | "}";
87 | }
88 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_emergency.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
25 |
26 |
35 |
36 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/data/MeetingsRepository.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.meetings.data;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.MutableLiveData;
5 |
6 | import com.kriticalflare.community.meetings.data.model.Meeting;
7 | import com.kriticalflare.community.meetings.data.model.MeetingDao;
8 | import com.kriticalflare.community.meetings.data.model.MeetingsResponse;
9 | import com.kriticalflare.community.network.ApiService;
10 | import com.kriticalflare.community.util.AppExecutor;
11 | import com.kriticalflare.community.util.NetworkBoundResource;
12 | import com.kriticalflare.community.util.Resource;
13 |
14 | import java.util.List;
15 |
16 | import javax.inject.Inject;
17 |
18 | import retrofit2.Call;
19 | import retrofit2.Response;
20 |
21 | public class MeetingsRepository {
22 | private AppExecutor appExecutor;
23 | private MeetingDao meetingDao;
24 | private NetworkBoundResource, MeetingsResponse> networkBoundResource;
25 | private ApiService apiService;
26 |
27 | @Inject
28 | public MeetingsRepository(AppExecutor appExecutor, MeetingDao meetingDao, ApiService apiService) {
29 | this.appExecutor = appExecutor;
30 | this.meetingDao = meetingDao;
31 | this.apiService = apiService;
32 | }
33 |
34 | public LiveData>> getMeetings(){
35 | networkBoundResource = new NetworkBoundResource, MeetingsResponse>(appExecutor) {
36 | @Override
37 | public List loadFromDatabase() {
38 | return meetingDao.getMeetings();
39 | }
40 |
41 | @Override
42 | public Call createApiCall() {
43 | return apiService.getMeetings();
44 | }
45 |
46 | @Override
47 | public void saveCallResult(MeetingsResponse item) {
48 | meetingDao.insertMeetings(item.getMeetingsList());
49 | }
50 |
51 | @Override
52 | public boolean isSuccessfulResponse(Response item) {
53 | return item.isSuccessful();
54 | }
55 | };
56 | return networkBoundResource.asLiveData();
57 | }
58 |
59 | public void refreshMeetings(){
60 | networkBoundResource.triggerNetworkRequest();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/data/EmergencyRepository.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.data;
2 |
3 | import androidx.lifecycle.LiveData;
4 |
5 | import com.kriticalflare.community.emergency.data.model.EmergencyDao;
6 | import com.kriticalflare.community.emergency.data.model.EmergencyItem;
7 | import com.kriticalflare.community.emergency.data.model.EmergencyResponse;
8 | import com.kriticalflare.community.network.ApiService;
9 | import com.kriticalflare.community.util.AppExecutor;
10 | import com.kriticalflare.community.util.NetworkBoundResource;
11 | import com.kriticalflare.community.util.Resource;
12 |
13 | import java.util.List;
14 |
15 | import javax.inject.Inject;
16 |
17 | import retrofit2.Call;
18 | import retrofit2.Response;
19 |
20 | public class EmergencyRepository {
21 | private AppExecutor appExecutor;
22 | private EmergencyDao emergencyDao;
23 | private NetworkBoundResource, EmergencyResponse> networkBoundResource;
24 | private ApiService apiService;
25 |
26 | @Inject
27 | public EmergencyRepository(AppExecutor appExecutor, EmergencyDao emergencyDao, ApiService apiService) {
28 | this.appExecutor = appExecutor;
29 | this.emergencyDao = emergencyDao;
30 | this.apiService = apiService;
31 | }
32 |
33 | public LiveData>> getEmergencies() {
34 | networkBoundResource = new NetworkBoundResource, EmergencyResponse>(appExecutor) {
35 | @Override
36 | public List loadFromDatabase() {
37 | return emergencyDao.getEmergencies();
38 | }
39 |
40 | @Override
41 | public Call createApiCall() {
42 | return apiService.getEmergencies();
43 | }
44 |
45 | @Override
46 | public void saveCallResult(EmergencyResponse item) {
47 | emergencyDao.insertEmergency(item.getEmergencyNumberList());
48 | }
49 |
50 | @Override
51 | public boolean isSuccessfulResponse(Response item) {
52 | return item.isSuccessful();
53 | }
54 | };
55 | return networkBoundResource.asLiveData();
56 | }
57 |
58 | public void refreshEmergencies(){
59 | networkBoundResource.triggerNetworkRequest();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_nav_sheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
21 |
22 |
31 |
32 |
40 |
41 |
42 |
43 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_meetings.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
17 |
24 |
25 |
26 |
38 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/data/EventsRepository.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events.data;
2 |
3 | import androidx.lifecycle.LiveData;
4 |
5 | import com.kriticalflare.community.emergency.data.model.EmergencyDao;
6 | import com.kriticalflare.community.emergency.data.model.EmergencyItem;
7 | import com.kriticalflare.community.emergency.data.model.EmergencyResponse;
8 | import com.kriticalflare.community.events.data.model.Events;
9 | import com.kriticalflare.community.events.data.model.EventsDao;
10 | import com.kriticalflare.community.events.data.model.EventsResponse;
11 | import com.kriticalflare.community.network.ApiService;
12 | import com.kriticalflare.community.util.AppExecutor;
13 | import com.kriticalflare.community.util.NetworkBoundResource;
14 | import com.kriticalflare.community.util.Resource;
15 |
16 | import java.util.List;
17 |
18 | import javax.inject.Inject;
19 |
20 | import retrofit2.Call;
21 | import retrofit2.Response;
22 |
23 | public class EventsRepository {
24 | private AppExecutor appExecutor;
25 | private EventsDao eventsDao;
26 | private NetworkBoundResource, EventsResponse> networkBoundResource;
27 | private ApiService apiService;
28 |
29 | @Inject
30 | public EventsRepository(AppExecutor appExecutor, EventsDao eventsDao, ApiService apiService) {
31 | this.appExecutor = appExecutor;
32 | this.eventsDao = eventsDao;
33 | this.apiService = apiService;
34 | }
35 |
36 | public LiveData>> getEvents() {
37 | networkBoundResource = new NetworkBoundResource, EventsResponse>(appExecutor) {
38 | @Override
39 | public List loadFromDatabase() {
40 | return eventsDao.getEvents();
41 | }
42 |
43 | @Override
44 | public Call createApiCall() {
45 | return apiService.getEvents();
46 | }
47 |
48 | @Override
49 | public void saveCallResult(EventsResponse item) {
50 | eventsDao.insertEvents(item.getEventList());
51 | }
52 |
53 | @Override
54 | public boolean isSuccessfulResponse(Response item) {
55 | return item.isSuccessful();
56 | }
57 | };
58 | return networkBoundResource.asLiveData();
59 | }
60 |
61 | public void refreshEvents(){
62 | networkBoundResource.triggerNetworkRequest();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_emergency.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
17 |
25 |
26 |
38 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_events.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
19 |
27 |
28 |
29 |
41 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/util/NetworkBoundResource.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.util;
2 |
3 | import androidx.annotation.WorkerThread;
4 | import androidx.lifecycle.MutableLiveData;
5 |
6 | import retrofit2.Call;
7 | import retrofit2.Callback;
8 | import retrofit2.Response;
9 |
10 |
11 | public abstract class NetworkBoundResource {
12 |
13 | private MutableLiveData> result = new MutableLiveData<>();
14 |
15 | private AppExecutor appExecutor;
16 |
17 |
18 | public NetworkBoundResource(AppExecutor appExecutor) {
19 | this.appExecutor = appExecutor;
20 | }
21 |
22 | @WorkerThread
23 | abstract public ResultType loadFromDatabase();
24 |
25 | @WorkerThread
26 | abstract public Call createApiCall();
27 |
28 | @WorkerThread
29 | abstract public void saveCallResult(RequestType item);
30 |
31 | abstract public boolean isSuccessfulResponse(Response item);
32 |
33 | public void triggerNetworkRequest() {
34 | appExecutor.networkIO().execute(this::loadFromNetwork);
35 | }
36 |
37 | private void loadFromNetwork() {
38 |
39 | result.postValue(Resource.loading(loadFromDatabase()));
40 |
41 | createApiCall().enqueue(new Callback() {
42 | @Override
43 | public void onResponse(Call call, Response response) {
44 | if (response.body() == null || String.valueOf(response.code()).matches("^[45].*")) {
45 | result.postValue(Resource.error(loadFromDatabase(),
46 | "Server is currently experiencing issues, try again after some time"));
47 | } else if (isSuccessfulResponse(response)) {
48 | saveCallResult(response.body());
49 | // TODO: postvalue from response itself? or check if loadFromDatabase is null
50 | result.postValue(Resource.success(loadFromDatabase()));
51 | } else {
52 | result.postValue(Resource.error(loadFromDatabase(), response.message()));
53 | }
54 | }
55 |
56 | @Override
57 | public void onFailure(Call call, Throwable t) {
58 | result.postValue(Resource.error(loadFromDatabase(),
59 | "Oops! Something went wrong"));
60 | }
61 | });
62 | }
63 |
64 | public MutableLiveData> asLiveData() {
65 | triggerNetworkRequest();
66 | return result;
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/app/src/main/res/values-night-v29/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
31 |
32 |
33 |
36 |
37 |
43 |
44 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
32 |
33 |
34 |
37 |
38 |
44 |
45 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v29/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
38 |
39 |
40 |
43 |
44 |
50 |
51 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
35 |
36 |
41 |
42 |
45 |
46 |
52 |
53 |
58 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/di/NetworkModule.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.di;
2 |
3 | import com.kriticalflare.community.data.local.PrefsDataStore;
4 | import com.kriticalflare.community.network.ApiService;
5 | import com.kriticalflare.community.network.AuthService;
6 | import com.kriticalflare.community.network.AuthenticatedService;
7 | import com.kriticalflare.community.network.TokenInterceptor;
8 | import com.kriticalflare.community.util.AppExecutor;
9 | import com.kriticalflare.community.util.Constants;
10 |
11 | import javax.inject.Named;
12 | import javax.inject.Singleton;
13 |
14 | import dagger.Module;
15 | import dagger.Provides;
16 | import dagger.hilt.InstallIn;
17 | import dagger.hilt.components.SingletonComponent;
18 | import okhttp3.OkHttpClient;
19 | import retrofit2.Retrofit;
20 | import okhttp3.logging.HttpLoggingInterceptor;
21 | import retrofit2.converter.gson.GsonConverterFactory;
22 |
23 | @Module
24 | @InstallIn(SingletonComponent.class)
25 | public class NetworkModule {
26 | @Singleton
27 | @Provides
28 | @Named("unauthenticated")
29 | public OkHttpClient provideOkHttpClient() {
30 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
31 | httpLoggingInterceptor.level(HttpLoggingInterceptor.Level.BODY);
32 | return new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor).build();
33 | }
34 |
35 | @Singleton
36 | @Provides
37 | @Named("authenticated")
38 | public OkHttpClient provideAuthOkHttpClient(PrefsDataStore dataStore) {
39 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
40 | httpLoggingInterceptor.level(HttpLoggingInterceptor.Level.BODY);
41 | TokenInterceptor tokenInterceptor = new TokenInterceptor(dataStore);
42 | return new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor).addInterceptor(tokenInterceptor).build();
43 | }
44 |
45 | @Singleton
46 | @Provides
47 | public AuthService provideAuthClientApi(@Named("unauthenticated") OkHttpClient okHttpClient, AppExecutor appExecutor) {
48 | return new Retrofit.Builder()
49 | .baseUrl(Constants.BASE_URL)
50 | .client(okHttpClient)
51 | .addConverterFactory(GsonConverterFactory.create())
52 | .callbackExecutor(appExecutor.networkIO())
53 | .build()
54 | .create(AuthService.class);
55 | }
56 |
57 | @Singleton
58 | @Provides
59 | public ApiService provideApiClient(@Named("unauthenticated") OkHttpClient okHttpClient, AppExecutor appExecutor) {
60 | return new Retrofit.Builder()
61 | .baseUrl(Constants.BASE_URL)
62 | .client(okHttpClient)
63 | .addConverterFactory(GsonConverterFactory.create())
64 | .callbackExecutor(appExecutor.networkIO())
65 | .build()
66 | .create(ApiService.class);
67 | }
68 |
69 | @Singleton
70 | @Provides
71 | public AuthenticatedService provideAuthenticatedClient(@Named("authenticated") OkHttpClient authOkHttpClient, AppExecutor appExecutor) {
72 | return new Retrofit.Builder()
73 | .baseUrl(Constants.BASE_URL)
74 | .client(authOkHttpClient)
75 | .addConverterFactory(GsonConverterFactory.create())
76 | .callbackExecutor(appExecutor.networkIO())
77 | .build()
78 | .create(AuthenticatedService.class);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
4 | }
5 | apply plugin: 'dagger.hilt.android.plugin'
6 |
7 |
8 | android {
9 | compileSdk 31
10 |
11 | defaultConfig {
12 | applicationId "com.kriticalflare.community"
13 | minSdk 24
14 | targetSdk 31
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | compileOptions {
28 | sourceCompatibility JavaVersion.VERSION_1_8
29 | targetCompatibility JavaVersion.VERSION_1_8
30 | }
31 | buildFeatures {
32 | viewBinding true
33 | }
34 | secrets {
35 | propertiesFileName 'secrets.properties'
36 | }
37 | }
38 |
39 | dependencies {
40 |
41 | def nav_version = "2.4.0-alpha09"
42 | def lottie_version = "4.1.0"
43 | def core_version = "1.6.0"
44 | def splash_version = "1.0.0-alpha01"
45 | def insetter_version = "0.6.0"
46 | def datastore_version = "1.0.0"
47 | def hilt_version = "2.38.1"
48 | def room_version = "2.3.0"
49 |
50 | // Java language implementation
51 | implementation "androidx.core:core:$core_version"
52 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
53 | implementation 'androidx.appcompat:appcompat:1.3.1'
54 | implementation 'com.google.android.material:material:1.4.0'
55 | implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
56 | testImplementation 'junit:junit:4.+'
57 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
58 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
59 | implementation "androidx.navigation:navigation-fragment:$nav_version"
60 | implementation "androidx.navigation:navigation-ui:$nav_version"
61 | implementation "com.airbnb.android:lottie:$lottie_version"
62 | implementation "androidx.core:core-splashscreen:$splash_version"
63 | implementation "dev.chrisbanes.insetter:insetter:$insetter_version"
64 | implementation "androidx.datastore:datastore-preferences-rxjava3:$datastore_version"
65 | implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
66 | implementation 'io.reactivex.rxjava3:rxjava:3.1.1'
67 | implementation "com.google.dagger:hilt-android:$hilt_version"
68 | annotationProcessor "com.google.dagger:hilt-compiler:$hilt_version"
69 | implementation "com.squareup.retrofit2:retrofit:2.9.0"
70 | implementation 'com.google.code.gson:gson:2.8.8'
71 | implementation 'com.squareup.okhttp3:logging-interceptor:4.8.1'
72 | implementation "com.squareup.retrofit2:converter-gson:2.9.0"
73 | implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
74 | implementation 'com.github.Zhuinden:event-emitter:1.2.0'
75 | implementation 'com.github.ybq:Android-SpinKit:1.4.0'
76 | implementation "androidx.room:room-runtime:$room_version"
77 | annotationProcessor "androidx.room:room-compiler:$room_version"
78 | implementation "com.google.android.gms:play-services-maps:17.0.1"
79 | implementation('com.journeyapps:zxing-android-embedded:4.2.0') { transitive = false }
80 | implementation 'com.google.zxing:core:3.3.0'
81 | implementation 'com.google.android.gms:play-services-location:18.0.0'
82 | implementation 'com.nambimobile.widgets:expandable-fab:1.1.1'
83 | }
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/home/HomeFragment.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.home;
2 |
3 | import android.os.Bundle;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import androidx.fragment.app.Fragment;
8 | import androidx.lifecycle.ViewModelProvider;
9 | import androidx.navigation.Navigation;
10 |
11 | import android.util.Log;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 |
16 | import com.google.android.material.transition.MaterialSharedAxis;
17 | import com.kriticalflare.community.AuthenticationViewModel;
18 | import com.kriticalflare.community.R;
19 | import com.kriticalflare.community.databinding.FragmentHomeBinding;
20 |
21 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
22 | import io.reactivex.rxjava3.disposables.CompositeDisposable;
23 | import io.reactivex.rxjava3.schedulers.Schedulers;
24 | import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
25 |
26 | public class HomeFragment extends Fragment {
27 |
28 | public static final String TAG = "HOME_FRAGMENT";
29 | private FragmentHomeBinding binding;
30 | private AuthenticationViewModel authViewModel;
31 | private CompositeDisposable compositeDisposable;
32 |
33 | public HomeFragment() {
34 | // Required empty public constructor
35 | }
36 |
37 | @Override
38 | public void onCreate(Bundle savedInstanceState) {
39 | this.setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, true));
40 | this.setReturnTransition(new MaterialSharedAxis(MaterialSharedAxis.X, false));
41 | super.onCreate(savedInstanceState);
42 | }
43 |
44 | @Override
45 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
46 | Bundle savedInstanceState) {
47 | // Inflate the layout for this fragment
48 | binding = FragmentHomeBinding.inflate(inflater, container, false);
49 | return binding.getRoot();
50 | }
51 |
52 | @Override
53 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
54 | super.onViewCreated(view, savedInstanceState);
55 | authViewModel = new ViewModelProvider(requireActivity()).get(AuthenticationViewModel.class);
56 | compositeDisposable = new CompositeDisposable();
57 | compositeDisposable.add(
58 | authViewModel.isLoggedIn()
59 | .subscribeOn(Schedulers.io())
60 | .observeOn(AndroidSchedulers.mainThread())
61 | .subscribeWith(new DisposableSubscriber() {
62 | @Override
63 | public void onNext(Boolean status) {
64 | Log.d(TAG, "LOGIN STATUS " + status);
65 | if(!status){
66 | Navigation.findNavController(binding.getRoot()).navigate(R.id.action_global_loginFragment);
67 | }
68 | request(1);
69 | }
70 |
71 | @Override
72 | public void onError(Throwable t) {
73 |
74 | }
75 |
76 | @Override
77 | public void onComplete() {
78 |
79 | }
80 | })
81 | );
82 |
83 | }
84 |
85 | @Override
86 | public void onDestroyView() {
87 | super.onDestroyView();
88 | compositeDisposable.dispose();
89 | binding = null;
90 | }
91 | }
--------------------------------------------------------------------------------
/app/src/main/res/navigation/nav_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
16 |
19 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
59 |
64 |
69 |
74 |
77 |
78 |
83 |
88 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_scanner.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
22 |
23 |
37 |
38 |
49 |
50 |
63 |
66 |
70 |
71 |
79 |
88 |
97 |
106 |
107 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/register/RegisterFragment.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.register;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.view.ViewTreeObserver;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.core.view.WindowInsetsCompat;
12 | import androidx.fragment.app.Fragment;
13 | import androidx.lifecycle.ViewModelProvider;
14 |
15 | import com.google.android.material.snackbar.Snackbar;
16 | import com.google.android.material.transition.MaterialSharedAxis;
17 | import com.kriticalflare.community.AuthenticationViewModel;
18 | import com.kriticalflare.community.databinding.FragmentRegisterBinding;
19 | import com.kriticalflare.community.model.RegisterUser;
20 | import com.zhuinden.eventemitter.EventSource;
21 |
22 | import dev.chrisbanes.insetter.Insetter;
23 |
24 |
25 | public class RegisterFragment extends Fragment {
26 | private FragmentRegisterBinding binding;
27 | private AuthenticationViewModel authViewModel;
28 | private EventSource.NotificationToken eventSubscription;
29 |
30 | @Override
31 | public void onCreate(Bundle savedInstanceState) {
32 | this.setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true));
33 | this.setReturnTransition(new MaterialSharedAxis(MaterialSharedAxis.X, false));
34 | this.setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true));
35 | this.setReenterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, false));
36 | super.onCreate(savedInstanceState);
37 | }
38 |
39 | @Override
40 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
41 | Bundle savedInstanceState) {
42 | // Inflate the layout for this fragment
43 | binding = FragmentRegisterBinding.inflate(inflater, container, false);
44 |
45 | binding.registerButton.setOnClickListener(view -> {
46 | if (binding.nameTextField.getEditText() != null
47 | && binding.emailTextField.getEditText() != null
48 | && binding.passwordTextfield.getEditText() != null
49 | && binding.roomNumberTextfield.getEditText() != null
50 | && binding.buildingNumberTextfield.getEditText() != null) {
51 | String name = binding.emailTextField.getEditText().getText().toString();
52 | String email = binding.emailTextField.getEditText().getText().toString();
53 | String password = binding.passwordTextfield.getEditText().getText().toString();
54 | String roomNumber = binding.roomNumberTextfield.getEditText().getText().toString();
55 | String buildingNumber = binding.buildingNumberTextfield.getEditText().getText().toString();
56 |
57 | if (!name.isEmpty()
58 | && !email.isEmpty()
59 | && !password.isEmpty()
60 | && !roomNumber.isEmpty()
61 | && !buildingNumber.isEmpty()) {
62 | RegisterUser user = new RegisterUser(name, email, password, roomNumber, buildingNumber);
63 | authViewModel.register(user);
64 | } else {
65 | makeSnackBar("Please enter all details");
66 | }
67 | }
68 | });
69 |
70 |
71 | return binding.getRoot();
72 | }
73 |
74 | @Override
75 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
76 | super.onViewCreated(view, savedInstanceState);
77 | this.postponeEnterTransition();
78 | view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
79 | @Override
80 | public boolean onPreDraw() {
81 | view.getViewTreeObserver().removeOnPreDrawListener(this);
82 | startPostponedEnterTransition();
83 | return true;
84 | }
85 | });
86 | authViewModel = new ViewModelProvider(requireActivity()).get(AuthenticationViewModel.class);
87 |
88 | eventSubscription = authViewModel.eventMessages.startListening(this::makeSnackBar);
89 | authViewModel.loading.observe(getViewLifecycleOwner(), loading -> {
90 | if (loading) {
91 | binding.registerButton.setVisibility(View.INVISIBLE);
92 | binding.progressIndicator.setVisibility(View.VISIBLE);
93 | } else {
94 | binding.registerButton.setVisibility(View.VISIBLE);
95 | binding.progressIndicator.setVisibility(View.INVISIBLE);
96 | }
97 | });
98 | }
99 |
100 | private void makeSnackBar(String message) {
101 | Snackbar.make(this.binding.rootLayout, message, Snackbar.LENGTH_LONG)
102 | .show();
103 | }
104 |
105 | @Override
106 | public void onDestroyView() {
107 | super.onDestroyView();
108 | binding = null;
109 | eventSubscription.stopListening();
110 | }
111 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/data/ParkingRepository.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.data;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.MutableLiveData;
5 |
6 | import com.kriticalflare.community.network.AuthenticatedService;
7 | import com.kriticalflare.community.parking.data.model.GetParkingResponse;
8 | import com.kriticalflare.community.parking.data.model.ParkingBody;
9 | import com.kriticalflare.community.parking.data.model.ParkingResponse;
10 | import com.kriticalflare.community.util.AppExecutor;
11 | import com.kriticalflare.community.util.Resource;
12 |
13 | import javax.inject.Inject;
14 |
15 | import retrofit2.Call;
16 | import retrofit2.Callback;
17 | import retrofit2.Response;
18 |
19 | public class ParkingRepository {
20 | AppExecutor appExecutor;
21 | AuthenticatedService authService;
22 |
23 | @Inject
24 | ParkingRepository(AppExecutor appExecutor, AuthenticatedService authService) {
25 | this.appExecutor = appExecutor;
26 | this.authService = authService;
27 | }
28 |
29 | public LiveData> getParkingSpots() {
30 | MutableLiveData> liveData = new MutableLiveData<>();
31 | liveData.postValue(Resource.loading(null));
32 | appExecutor.networkIO().execute(() -> {
33 | authService.getParkingSpots().enqueue(new Callback() {
34 | @Override
35 | public void onResponse(Call call, Response response) {
36 | if (response.isSuccessful() && response.body() != null) {
37 | liveData.postValue(Resource.success(response.body()));
38 | } else {
39 | liveData.postValue(Resource.error(null, response.message()));
40 | }
41 | }
42 |
43 | @Override
44 | public void onFailure(Call call, Throwable t) {
45 | liveData.postValue(Resource.error(null, t.getMessage()));
46 | }
47 | });
48 | });
49 | return liveData;
50 | }
51 |
52 | public LiveData> claimParkingSpots(String qrCode) {
53 | MutableLiveData> liveData = new MutableLiveData<>();
54 | liveData.postValue(Resource.loading(null));
55 | appExecutor.networkIO().execute(() -> {
56 | ParkingBody parkingBody = new ParkingBody(qrCode);
57 | authService.claimParkingSpot(parkingBody).enqueue(new Callback() {
58 | @Override
59 | public void onResponse(Call call, Response response) {
60 | if (response.isSuccessful() && response.body() != null && response.body().isParked()) {
61 | liveData.postValue(Resource.success(response.body()));
62 | } else {
63 | if (response.body() != null) {
64 | liveData.postValue(Resource.error(response.body(), response.message()));
65 | } else {
66 | liveData.postValue(Resource.error(null, "Internal Server Error"));
67 | }
68 | }
69 | }
70 |
71 | @Override
72 | public void onFailure(Call call, Throwable t) {
73 | liveData.postValue(Resource.error(null, t.getMessage()));
74 | }
75 | });
76 | });
77 |
78 | return liveData;
79 | }
80 |
81 | public LiveData> clearParkingSpot(String qrCode) {
82 | MutableLiveData> liveData = new MutableLiveData<>();
83 | liveData.postValue(Resource.loading(null));
84 | appExecutor.networkIO().execute(() -> {
85 | ParkingBody parkingBody = new ParkingBody(qrCode);
86 | authService.clearParkingSpot(parkingBody).enqueue(new Callback() {
87 | @Override
88 | public void onResponse(Call call, Response response) {
89 | if (response.isSuccessful() && response.body() != null && response.body().isParked()) {
90 | liveData.postValue(Resource.success(response.body()));
91 | } else {
92 | if (response.body() != null) {
93 | liveData.postValue(Resource.error(response.body(), response.message()));
94 | } else {
95 | liveData.postValue(Resource.error(null, "Internal Server Error"));
96 | }
97 | }
98 | }
99 |
100 | @Override
101 | public void onFailure(Call call, Throwable t) {
102 | liveData.postValue(Resource.error(null, t.getMessage()));
103 | }
104 | });
105 | });
106 |
107 | return liveData;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/data/AuthenticationRepository.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.data;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.datastore.preferences.core.MutablePreferences;
5 | import androidx.datastore.preferences.core.Preferences;
6 | import androidx.datastore.preferences.core.PreferencesKeys;
7 | import androidx.datastore.rxjava3.RxDataStore;
8 | import androidx.lifecycle.LiveData;
9 | import androidx.lifecycle.MutableLiveData;
10 |
11 | import com.kriticalflare.community.data.local.PrefsDataStore;
12 | import com.kriticalflare.community.model.LoginResponse;
13 | import com.kriticalflare.community.model.LoginUser;
14 | import com.kriticalflare.community.model.RegisterUser;
15 | import com.kriticalflare.community.network.AuthService;
16 | import com.kriticalflare.community.util.AppExecutor;
17 | import com.zhuinden.eventemitter.EventEmitter;
18 | import com.zhuinden.eventemitter.EventSource;
19 |
20 | import java.util.Optional;
21 |
22 | import javax.inject.Inject;
23 |
24 | import io.reactivex.rxjava3.core.Flowable;
25 | import io.reactivex.rxjava3.core.Single;
26 | import retrofit2.Call;
27 | import retrofit2.Callback;
28 | import retrofit2.Response;
29 |
30 |
31 | public class AuthenticationRepository {
32 |
33 | private PrefsDataStore dataStore;
34 | private final AuthService authService;
35 | private final EventEmitter emitter;
36 | public EventSource errorEvents;
37 | private final MutableLiveData _loadingLiveData;
38 | public LiveData loading;
39 | private AppExecutor appExecutor;
40 |
41 | @Inject
42 | AuthenticationRepository(PrefsDataStore dataStore, AuthService authService, AppExecutor appExecutor) {
43 | this.dataStore = dataStore;
44 | this.authService = authService;
45 | this.appExecutor = appExecutor;
46 | emitter = new EventEmitter<>();
47 | _loadingLiveData = new MutableLiveData<>(false);
48 | loading = _loadingLiveData;
49 | errorEvents = emitter;
50 | }
51 |
52 | public void register(RegisterUser user) {
53 | _loadingLiveData.setValue(true);
54 | authService.registerUser(user).enqueue(new Callback() {
55 | @Override
56 | public void onResponse(Call call, Response response) {
57 | if (response.isSuccessful()) {
58 | _loadingLiveData.postValue(false);
59 | appExecutor.mainThread().execute(() -> {
60 | emitter.emit("Registration Successful");
61 | });
62 |
63 | } else {
64 | _loadingLiveData.postValue(false);
65 | appExecutor.mainThread().execute(() -> {
66 | emitter.emit(response.message());
67 | });
68 | }
69 | }
70 |
71 | @Override
72 | public void onFailure(Call call, Throwable t) {
73 | _loadingLiveData.postValue(false);
74 | appExecutor.mainThread().execute(() -> {
75 | emitter.emit("Registration failed");
76 | });
77 | }
78 | });
79 | }
80 |
81 | public void login(LoginUser user) {
82 | _loadingLiveData.setValue(true);
83 | authService.login(user).enqueue(new Callback() {
84 | @Override
85 | public void onResponse(@NonNull Call call, @NonNull Response response) {
86 | if (response.isSuccessful()) {
87 | _loadingLiveData.postValue(false);
88 | if(response.body() != null){
89 | dataStore.saveEmail(user.email);
90 | dataStore.saveToken(response.body().getToken());
91 | dataStore.saveLoginStatus(true);
92 | } else {
93 | dataStore.saveLoginStatus(false);
94 | }
95 | } else {
96 | _loadingLiveData.postValue(false);
97 | appExecutor.mainThread().execute(() -> {
98 | emitter.emit("Check your credentials");
99 | });
100 |
101 | }
102 | }
103 |
104 | @Override
105 | public void onFailure(@NonNull Call call, @NonNull Throwable t) {
106 | _loadingLiveData.postValue(false);
107 | appExecutor.mainThread().execute(() -> {
108 | emitter.emit("Login failed");
109 | });
110 | dataStore.saveLoginStatus(false);
111 | }
112 | });
113 | }
114 |
115 | public void logout() {
116 | dataStore.saveEmail("");
117 | dataStore.saveLoginStatus(false);
118 | dataStore.saveToken("");
119 | }
120 |
121 | public void saveLoginStatus(boolean status){
122 | dataStore.saveLoginStatus(status);
123 | }
124 |
125 | public Flowable getLoginStatus() {
126 | return dataStore.getLoginStatus();
127 | }
128 |
129 | public Flowable getJWTToken() {
130 | return dataStore.getJWTToken();
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/emergency/ui/EmergencyFragment.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.emergency.ui;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import androidx.annotation.NonNull;
9 | import androidx.annotation.Nullable;
10 | import androidx.fragment.app.Fragment;
11 | import androidx.lifecycle.ViewModelProvider;
12 | import androidx.navigation.Navigation;
13 | import androidx.recyclerview.widget.LinearLayoutManager;
14 |
15 | import com.google.android.material.transition.MaterialSharedAxis;
16 | import com.kriticalflare.community.AuthenticationViewModel;
17 | import com.kriticalflare.community.R;
18 | import com.kriticalflare.community.databinding.FragmentEmergencyBinding;
19 |
20 | import dagger.hilt.android.AndroidEntryPoint;
21 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
22 | import io.reactivex.rxjava3.disposables.CompositeDisposable;
23 | import io.reactivex.rxjava3.schedulers.Schedulers;
24 | import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
25 |
26 | @AndroidEntryPoint
27 | public class EmergencyFragment extends Fragment {
28 |
29 | public EmergencyFragment() {
30 | // Required empty public constructor
31 | }
32 |
33 | private AuthenticationViewModel authViewModel;
34 | private CompositeDisposable compositeDisposable;
35 | private EmergencyViewModel emergencyViewModel;
36 | private FragmentEmergencyBinding binding;
37 | private EmergencyAdapter emergencyAdapter;
38 |
39 | @Override
40 | public void onCreate(@Nullable Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, true));
43 | setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, false));
44 | }
45 |
46 | @Nullable
47 | @Override
48 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
49 | super.onCreateView(inflater, container, savedInstanceState);
50 | binding = FragmentEmergencyBinding.inflate(inflater, container,false);
51 | emergencyAdapter = new EmergencyAdapter();
52 | binding.emergencyRecycler.setAdapter(emergencyAdapter);
53 | binding.emergencyRecycler.setLayoutManager(new LinearLayoutManager(getContext()));
54 | return binding.getRoot();
55 | }
56 |
57 | @Override
58 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
59 | super.onViewCreated(view, savedInstanceState);
60 | authViewModel = new ViewModelProvider(requireActivity()).get(AuthenticationViewModel.class);
61 | compositeDisposable = new CompositeDisposable();
62 | compositeDisposable.add(authViewModel.isLoggedIn()
63 | .subscribeOn(Schedulers.io())
64 | .observeOn(AndroidSchedulers.mainThread())
65 | .subscribeWith(new DisposableSubscriber() {
66 | @Override
67 | public void onNext(Boolean status) {
68 | if(!status){
69 | Navigation.findNavController(binding.getRoot()).navigate(R.id.action_global_loginFragment);
70 | }
71 | request(1);
72 | }
73 |
74 | @Override
75 | public void onError(Throwable t) {
76 |
77 | }
78 |
79 | @Override
80 | public void onComplete() {
81 |
82 | }
83 | }));
84 |
85 | emergencyViewModel = new ViewModelProvider(this).get(EmergencyViewModel.class);
86 |
87 | emergencyViewModel.getEmergencies().observe(getViewLifecycleOwner(), listResource -> {
88 | switch (listResource.status) {
89 | case SUCCESS:
90 | emergencyAdapter.submitList(listResource.data);
91 | binding.emergencyRecycler.setVisibility(View.VISIBLE);
92 | binding.progressIndicator.setVisibility(View.GONE);
93 | binding.statusMessage.setVisibility(View.GONE);
94 | break;
95 | case LOADING:
96 | binding.emergencyRecycler.setVisibility(View.GONE);
97 | binding.progressIndicator.setVisibility(View.VISIBLE);
98 | binding.statusMessage.setVisibility(View.GONE);
99 | break;
100 | case ERROR:
101 | case NO_NETWORK:
102 | binding.emergencyRecycler.setVisibility(View.GONE);
103 | binding.progressIndicator.setVisibility(View.GONE);
104 | binding.statusMessage.setText(listResource.apiMessage);
105 | binding.statusMessage.setVisibility(View.VISIBLE);
106 | break;
107 | }
108 | });
109 | binding.swipeRefresh.setOnRefreshListener(() -> {
110 | emergencyViewModel.refreshEmergencies();
111 | Runnable runnable = () -> binding.swipeRefresh.setRefreshing(false);
112 | binding.swipeRefresh.postDelayed(runnable, 1000);
113 | });
114 | }
115 |
116 | @Override
117 | public void onDestroyView() {
118 | super.onDestroyView();
119 | binding = null;
120 | compositeDisposable.dispose();
121 | }
122 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
17 |
26 |
27 |
37 |
47 |
51 |
52 |
53 |
64 |
68 |
69 |
70 |
74 |
83 |
95 |
96 |
97 |
98 |
110 |
116 |
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/events/EventsFragment.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.events;
2 |
3 | import android.os.Bundle;
4 | import android.util.Log;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.fragment.app.Fragment;
12 | import androidx.lifecycle.ViewModelProvider;
13 | import androidx.navigation.Navigation;
14 | import androidx.recyclerview.widget.LinearLayoutManager;
15 |
16 | import com.google.android.material.transition.MaterialSharedAxis;
17 | import com.kriticalflare.community.AuthenticationViewModel;
18 | import com.kriticalflare.community.R;
19 | import com.kriticalflare.community.databinding.FragmentEventsBinding;
20 |
21 | import dagger.hilt.android.AndroidEntryPoint;
22 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
23 | import io.reactivex.rxjava3.disposables.CompositeDisposable;
24 | import io.reactivex.rxjava3.schedulers.Schedulers;
25 | import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
26 |
27 | @AndroidEntryPoint
28 | public class EventsFragment extends Fragment {
29 |
30 |
31 | public static final String TAG = "EVENTS_FRAGMENT";
32 | private FragmentEventsBinding binding;
33 | private AuthenticationViewModel authViewModel;
34 | private EventsViewModel eventsViewModel;
35 | private CompositeDisposable compositeDisposable;
36 | private EventsAdapter eventsAdapter;
37 |
38 | public EventsFragment() {
39 | // Required empty public constructor
40 | }
41 |
42 | @Override
43 | public void onCreate(Bundle savedInstanceState) {
44 | super.onCreate(savedInstanceState);
45 | setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, true));
46 | setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, false));
47 | }
48 |
49 | @Override
50 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
51 | Bundle savedInstanceState) {
52 | // Inflate the layout for this fragment
53 | binding = FragmentEventsBinding.inflate(inflater, container, false);
54 | eventsAdapter = new EventsAdapter();
55 | binding.eventsRecycler.setAdapter(eventsAdapter);
56 | binding.eventsRecycler.setLayoutManager(new LinearLayoutManager(this.getContext()));
57 | return binding.getRoot();
58 | }
59 |
60 | @Override
61 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
62 | super.onViewCreated(view, savedInstanceState);
63 | authViewModel = new ViewModelProvider(requireActivity()).get(AuthenticationViewModel.class);
64 | eventsViewModel = new ViewModelProvider(this).get(EventsViewModel.class);
65 | compositeDisposable = new CompositeDisposable();
66 | compositeDisposable.add(
67 | authViewModel.isLoggedIn()
68 | .subscribeOn(Schedulers.io())
69 | .observeOn(AndroidSchedulers.mainThread())
70 | .subscribeWith(new DisposableSubscriber() {
71 | @Override
72 | public void onNext(Boolean status) {
73 | Log.d(TAG, "LOGIN STATUS " + status);
74 | if (!status) {
75 | Navigation.findNavController(binding.getRoot()).navigate(R.id.action_global_loginFragment);
76 | }
77 | request(1);
78 | }
79 |
80 | @Override
81 | public void onError(Throwable t) {
82 |
83 | }
84 |
85 | @Override
86 | public void onComplete() {
87 |
88 | }
89 | })
90 | );
91 | eventsViewModel.getEvents().observe(getViewLifecycleOwner(), listResource -> {
92 | switch (listResource.status) {
93 | case SUCCESS:
94 | eventsAdapter.submitList(listResource.data);
95 | binding.eventsRecycler.setVisibility(View.VISIBLE);
96 | binding.progressIndicator.setVisibility(View.GONE);
97 | binding.statusMessage.setVisibility(View.GONE);
98 | break;
99 | case LOADING:
100 | binding.eventsRecycler.setVisibility(View.GONE);
101 | binding.progressIndicator.setVisibility(View.VISIBLE);
102 | binding.statusMessage.setVisibility(View.GONE);
103 | break;
104 | case ERROR:
105 | case NO_NETWORK:
106 | binding.eventsRecycler.setVisibility(View.GONE);
107 | binding.progressIndicator.setVisibility(View.GONE);
108 | binding.statusMessage.setText(listResource.apiMessage);
109 | binding.statusMessage.setVisibility(View.VISIBLE);
110 | break;
111 | }
112 | });
113 | binding.swipeRefresh.setOnRefreshListener(() -> {
114 | eventsViewModel.refreshEvents();
115 | Runnable runnable = () -> binding.swipeRefresh.setRefreshing(false);
116 | binding.swipeRefresh.postDelayed(runnable, 1000);
117 | });
118 | }
119 |
120 | @Override
121 | public void onDestroyView() {
122 | super.onDestroyView();
123 | compositeDisposable.dispose();
124 | }
125 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/login/LoginFragment.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.login;
2 |
3 | import android.os.Bundle;
4 | import android.util.Log;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.core.view.WindowInsetsCompat;
12 | import androidx.fragment.app.Fragment;
13 | import androidx.lifecycle.Observer;
14 | import androidx.lifecycle.ViewModelProvider;
15 | import androidx.navigation.Navigation;
16 |
17 | import com.google.android.material.snackbar.Snackbar;
18 | import com.google.android.material.transition.MaterialSharedAxis;
19 | import com.kriticalflare.community.AuthenticationViewModel;
20 | import com.kriticalflare.community.R;
21 | import com.kriticalflare.community.databinding.FragmentLoginBinding;
22 | import com.kriticalflare.community.model.LoginUser;
23 | import com.zhuinden.eventemitter.EventSource;
24 |
25 | import dev.chrisbanes.insetter.Insetter;
26 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
27 | import io.reactivex.rxjava3.disposables.CompositeDisposable;
28 | import io.reactivex.rxjava3.schedulers.Schedulers;
29 | import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
30 |
31 | public class LoginFragment extends Fragment {
32 |
33 |
34 | private FragmentLoginBinding binding;
35 | private AuthenticationViewModel authViewModel;
36 | private CompositeDisposable compositeDisposable;
37 | public static final String TAG = "LOGIN_FRAGMENT";
38 | private EventSource.NotificationToken eventSubscription;
39 |
40 | public LoginFragment() {
41 | // Required empty public constructor
42 | }
43 |
44 | public static LoginFragment newInstance(String param1, String param2) {
45 | LoginFragment fragment = new LoginFragment();
46 | return fragment;
47 | }
48 |
49 | @Override
50 | public void onCreate(Bundle savedInstanceState) {
51 | this.setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true));
52 | this.setReenterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, false));
53 | this.setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, true));
54 | this.setReturnTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, false));
55 | super.onCreate(savedInstanceState);
56 | }
57 |
58 | @Override
59 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
60 | Bundle savedInstanceState) {
61 | // Inflate the layout for this fragment
62 | binding = FragmentLoginBinding.inflate(inflater, container, false);
63 | binding.loginButton.setOnClickListener(view -> {
64 | if (binding.emailTextfield.getEditText() != null
65 | && binding.passwordTextfield.getEditText() != null
66 | ) {
67 | String email = binding.emailTextfield.getEditText().getText().toString();
68 | String password = binding.passwordTextfield.getEditText().getText().toString();
69 | if (!email.isEmpty() && !password.isEmpty()) {
70 | authViewModel.login(new LoginUser(email, password));
71 | } else {
72 | makeSnackBar("Check your credentials");
73 | }
74 | }
75 | });
76 | binding.registerButton.setOnClickListener(view -> Navigation.findNavController(view).navigate(R.id.action_loginFragment_to_registerFragment));
77 | return binding.getRoot();
78 | }
79 |
80 | @Override
81 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
82 | super.onViewCreated(view, savedInstanceState);
83 | authViewModel = new ViewModelProvider(requireActivity()).get(AuthenticationViewModel.class);
84 | compositeDisposable = new CompositeDisposable();
85 | compositeDisposable.add(
86 | authViewModel.isLoggedIn()
87 | .subscribeOn(Schedulers.io())
88 | .observeOn(AndroidSchedulers.mainThread())
89 | .subscribeWith(new DisposableSubscriber() {
90 | @Override
91 | public void onNext(Boolean status) {
92 | Log.d(TAG, "LOGIN STATUS " + status);
93 | if (status) {
94 | Navigation.findNavController(binding.getRoot()).popBackStack(R.id.meetingsFragment, false);
95 | }
96 | request(1);
97 | }
98 |
99 | @Override
100 | public void onError(Throwable t) {
101 |
102 | }
103 |
104 | @Override
105 | public void onComplete() {
106 |
107 | }
108 | })
109 | );
110 | eventSubscription = authViewModel.eventMessages.startListening(this::makeSnackBar);
111 | authViewModel.loading.observe(getViewLifecycleOwner(), loading -> {
112 | if(loading){
113 | binding.loginButton.setVisibility(View.INVISIBLE);
114 | binding.progressIndicator.setVisibility(View.VISIBLE);
115 | } else {
116 | binding.loginButton.setVisibility(View.VISIBLE);
117 | binding.progressIndicator.setVisibility(View.INVISIBLE);
118 | }
119 | });
120 |
121 | }
122 |
123 | private void makeSnackBar(String message) {
124 | Snackbar.make(this.binding.rootLayout, message, Snackbar.LENGTH_LONG)
125 | .show();
126 | }
127 |
128 | @Override
129 | public void onDestroyView() {
130 | super.onDestroyView();
131 | binding = null;
132 | compositeDisposable.dispose();
133 | eventSubscription.stopListening();
134 | }
135 |
136 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/meetings/ui/MeetingsFragment.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.meetings.ui;
2 |
3 | import android.os.Bundle;
4 | import android.util.Log;
5 | import android.util.TypedValue;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.view.ViewTreeObserver;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.annotation.Nullable;
13 | import androidx.core.view.WindowInsetsCompat;
14 | import androidx.fragment.app.Fragment;
15 | import androidx.lifecycle.ViewModelProvider;
16 | import androidx.navigation.Navigation;
17 | import androidx.recyclerview.widget.LinearLayoutManager;
18 |
19 | import com.google.android.material.transition.MaterialSharedAxis;
20 | import com.kriticalflare.community.AuthenticationViewModel;
21 | import com.kriticalflare.community.R;
22 | import com.kriticalflare.community.databinding.FragmentMeetingsBinding;
23 |
24 | import dagger.hilt.android.AndroidEntryPoint;
25 | import dev.chrisbanes.insetter.Insetter;
26 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
27 | import io.reactivex.rxjava3.disposables.CompositeDisposable;
28 | import io.reactivex.rxjava3.schedulers.Schedulers;
29 | import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
30 |
31 | @AndroidEntryPoint
32 | public class MeetingsFragment extends Fragment {
33 |
34 |
35 | private FragmentMeetingsBinding binding;
36 | private AuthenticationViewModel authViewModel;
37 | private MeetingsViewModel meetingsViewModel;
38 | private CompositeDisposable compositeDisposable;
39 | private MeetingsAdapter meetingsAdapter;
40 |
41 | public static final String TAG = "MEETINGS_FRAGMENT";
42 |
43 | public MeetingsFragment() {
44 | // Required empty public constructor
45 | }
46 |
47 | @Override
48 | public void onCreate(@Nullable Bundle savedInstanceState) {
49 | super.onCreate(savedInstanceState);
50 | setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, true));
51 | setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, true));
52 | setReenterTransition(new MaterialSharedAxis(MaterialSharedAxis.Z, true));
53 | }
54 |
55 | @Override
56 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
57 | Bundle savedInstanceState) {
58 | // Inflate the layout for this fragment
59 | binding = FragmentMeetingsBinding.inflate(inflater, container, false);
60 | Insetter.builder()
61 | .paddingBottom(WindowInsetsCompat.Type.navigationBars(), false)
62 | .applyToView(binding.getRoot());
63 | TypedValue tv = new TypedValue();
64 | if (requireContext().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
65 | int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
66 | binding.meetingsRecycler.setPadding(0, 0, 0, actionBarHeight);
67 | }
68 | meetingsAdapter = new MeetingsAdapter();
69 | binding.meetingsRecycler.setAdapter(meetingsAdapter);
70 | binding.meetingsRecycler.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
71 | return binding.getRoot();
72 | }
73 |
74 | @Override
75 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
76 | super.onViewCreated(view, savedInstanceState);
77 | postponeEnterTransition();
78 | view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
79 | @Override
80 | public boolean onPreDraw() {
81 | view.getViewTreeObserver().removeOnPreDrawListener(this);
82 | startPostponedEnterTransition();
83 | return true;
84 | }
85 | });
86 | authViewModel = new ViewModelProvider(requireActivity()).get(AuthenticationViewModel.class);
87 | meetingsViewModel = new ViewModelProvider(this).get(MeetingsViewModel.class);
88 | compositeDisposable = new CompositeDisposable();
89 | compositeDisposable.add(
90 | authViewModel.isLoggedIn()
91 | .subscribeOn(Schedulers.io())
92 | .observeOn(AndroidSchedulers.mainThread())
93 | .subscribeWith(new DisposableSubscriber() {
94 | @Override
95 | public void onNext(Boolean status) {
96 | Log.d(TAG, "LOGIN STATUS " + status);
97 | if (!status) {
98 | Navigation.findNavController(binding.getRoot()).navigate(R.id.action_global_loginFragment);
99 | }
100 | request(1);
101 | }
102 |
103 | @Override
104 | public void onError(Throwable t) {
105 |
106 | }
107 |
108 | @Override
109 | public void onComplete() {
110 |
111 | }
112 | })
113 | );
114 | meetingsViewModel.meetings.observe(getViewLifecycleOwner(), listResource -> {
115 | // listResource.data.addAll(listResource.data);
116 | switch (listResource.status) {
117 | case SUCCESS:
118 | meetingsAdapter.submitList(listResource.data);
119 | binding.meetingsRecycler.setVisibility(View.VISIBLE);
120 | binding.progressIndicator.setVisibility(View.GONE);
121 | binding.statusMessage.setVisibility(View.GONE);
122 | break;
123 | case LOADING:
124 | binding.meetingsRecycler.setVisibility(View.GONE);
125 | binding.progressIndicator.setVisibility(View.VISIBLE);
126 | binding.statusMessage.setVisibility(View.GONE);
127 | break;
128 | case ERROR:
129 | case NO_NETWORK:
130 | binding.meetingsRecycler.setVisibility(View.GONE);
131 | binding.progressIndicator.setVisibility(View.GONE);
132 | binding.statusMessage.setText(listResource.apiMessage);
133 | binding.statusMessage.setVisibility(View.VISIBLE);
134 | break;
135 | }
136 | });
137 |
138 | binding.swipeRefresh.setOnRefreshListener(() -> {
139 | meetingsViewModel.refreshMeetings();
140 | Runnable runnable = () -> binding.swipeRefresh.setRefreshing(false);
141 | binding.swipeRefresh.postDelayed(runnable, 1000);
142 | });
143 | }
144 |
145 | @Override
146 | public void onDestroyView() {
147 | super.onDestroyView();
148 | binding = null;
149 | compositeDisposable.dispose();
150 | }
151 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_register.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
17 |
27 |
28 |
38 |
48 |
52 |
53 |
63 |
67 |
68 |
69 |
80 |
84 |
85 |
86 |
96 |
100 |
101 |
102 |
112 |
116 |
117 |
118 |
119 |
123 |
132 |
144 |
145 |
149 |
150 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kriticalflare/community/parking/ui/ScannerFragment.java:
--------------------------------------------------------------------------------
1 | package com.kriticalflare.community.parking.ui;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.Toast;
11 |
12 | import androidx.annotation.NonNull;
13 | import androidx.annotation.Nullable;
14 | import androidx.core.view.WindowInsetsCompat;
15 | import androidx.fragment.app.Fragment;
16 | import androidx.lifecycle.Observer;
17 | import androidx.lifecycle.ViewModelProvider;
18 | import androidx.navigation.Navigation;
19 |
20 | import com.google.android.material.color.MaterialColors;
21 | import com.google.android.material.transition.MaterialArcMotion;
22 | import com.google.android.material.transition.MaterialContainerTransform;
23 | import com.google.zxing.integration.android.IntentIntegrator;
24 | import com.google.zxing.integration.android.IntentResult;
25 | import com.kriticalflare.community.AuthenticationViewModel;
26 | import com.kriticalflare.community.R;
27 | import com.kriticalflare.community.databinding.FragmentScannerBinding;
28 | import com.kriticalflare.community.parking.data.model.ParkingResponse;
29 | import com.kriticalflare.community.util.Resource;
30 |
31 | import dagger.hilt.android.AndroidEntryPoint;
32 | import dev.chrisbanes.insetter.Insetter;
33 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
34 | import io.reactivex.rxjava3.disposables.CompositeDisposable;
35 | import io.reactivex.rxjava3.schedulers.Schedulers;
36 | import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
37 |
38 | @AndroidEntryPoint
39 | public class ScannerFragment extends Fragment {
40 |
41 | private static final String TAG = "SCANNER_FRAGMENT";
42 |
43 | public ScannerFragment() {
44 | // Required empty public constructor
45 | }
46 |
47 | private FragmentScannerBinding binding;
48 | private AuthenticationViewModel authenticationViewModel;
49 | private ScannerViewModel scannerViewModel;
50 | private CompositeDisposable compositeDisposable;
51 |
52 |
53 | @Override
54 | public void onCreate(@Nullable Bundle savedInstanceState) {
55 | super.onCreate(savedInstanceState);
56 | MaterialContainerTransform transform = new MaterialContainerTransform();
57 | transform.setFadeMode(MaterialContainerTransform.FADE_MODE_CROSS);
58 | transform.setScrimColor(Color.TRANSPARENT);
59 | transform.setPathMotion(new MaterialArcMotion());
60 | transform.setAllContainerColors(MaterialColors.getColor(requireContext(), R.attr.colorSurface, Color.GRAY));
61 | setSharedElementEnterTransition(transform);
62 | }
63 |
64 | @Override
65 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
66 | Bundle savedInstanceState) {
67 | // Inflate the layout for this fragment
68 | binding = FragmentScannerBinding.inflate(inflater, container, false);
69 | binding.scanFab.setOnClickListener(v -> {
70 | IntentIntegrator.forSupportFragment(this)
71 | .setOrientationLocked(false)
72 | .setBarcodeImageEnabled(true)
73 | .setPrompt("Scan a QRCODE")
74 | .initiateScan();
75 | });
76 | return binding.getRoot();
77 | }
78 |
79 | @Override
80 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
81 | super.onViewCreated(view, savedInstanceState);
82 | Insetter.builder()
83 | .padding(WindowInsetsCompat.Type.systemBars())
84 | .applyToView(binding.getRoot());
85 | authenticationViewModel = new ViewModelProvider(requireActivity()).get(AuthenticationViewModel.class);
86 | scannerViewModel = new ViewModelProvider(this).get(ScannerViewModel.class);
87 | compositeDisposable = new CompositeDisposable();
88 | compositeDisposable.add(
89 | authenticationViewModel.isLoggedIn()
90 | .subscribeOn(Schedulers.io())
91 | .observeOn(AndroidSchedulers.mainThread())
92 | .subscribeWith(new DisposableSubscriber() {
93 | @Override
94 | public void onNext(Boolean status) {
95 | Log.d(TAG, "LOGIN STATUS " + status);
96 | if (!status) {
97 | Navigation.findNavController(binding.getRoot()).navigate(R.id.action_global_loginFragment);
98 | }
99 | request(1);
100 | }
101 |
102 | @Override
103 | public void onError(Throwable t) {
104 |
105 | }
106 |
107 | @Override
108 | public void onComplete() {
109 |
110 | }
111 | })
112 | );
113 |
114 | binding.claimParkingFab.setOnClickListener(v -> {
115 | scannerViewModel.claimParkingSpot(binding.scanResult.getText().toString())
116 | .observe(getViewLifecycleOwner(), parkingResource -> {
117 | String message = parkingResource.data != null ? parkingResource.data.getMessage() : parkingResource.apiMessage;
118 | switch (parkingResource.status){
119 | case SUCCESS:
120 | Toast.makeText(requireContext(), "Successful", Toast.LENGTH_SHORT).show();
121 | break;
122 | case ERROR:
123 | Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show();
124 | break;
125 | case LOADING:
126 | break;
127 | case NO_NETWORK:
128 | Toast.makeText(requireContext(), "Check your internet", Toast.LENGTH_SHORT).show();
129 | break;
130 | }
131 | });
132 | });
133 |
134 | binding.clearParkingFab.setOnClickListener(v -> {
135 | scannerViewModel.clearParkingSpot(binding.scanResult.getText().toString())
136 | .observe(getViewLifecycleOwner(), parkingResource -> {
137 | String message = parkingResource.data != null ? parkingResource.data.getMessage() : parkingResource.apiMessage;
138 | switch (parkingResource.status){
139 | case SUCCESS:
140 | Toast.makeText(requireContext(), "Successful", Toast.LENGTH_SHORT).show();
141 | break;
142 | case ERROR:
143 | Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show();
144 | break;
145 | case LOADING:
146 | break;
147 | case NO_NETWORK:
148 | Toast.makeText(requireContext(), "Check your internet", Toast.LENGTH_SHORT).show();
149 | break;
150 | }
151 | });
152 | });
153 | }
154 |
155 | @Override
156 | public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
157 | IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
158 | if (result != null) {
159 | if (result.getContents() == null) {
160 | Toast.makeText(getContext(), "Cancelled", Toast.LENGTH_LONG).show();
161 | } else {
162 | binding.scanResult.setText(result.getContents());
163 | }
164 | } else {
165 | super.onActivityResult(requestCode, resultCode, data);
166 | }
167 | }
168 |
169 | @Override
170 | public void onDestroyView() {
171 | super.onDestroyView();
172 | binding = null;
173 | compositeDisposable.clear();
174 | }
175 | }
--------------------------------------------------------------------------------