├── .gitignore ├── .idea ├── assetWizardSettings.xml ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro ├── release │ ├── Simple Timetable.apk │ ├── output.json │ └── release │ │ └── app.aab └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── appsforfun │ │ └── sam │ │ └── collegeapp310 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_logo_1-web.png │ ├── ic_logo_2-web.png │ ├── ic_mylogo-web.png │ ├── java │ │ └── com │ │ │ └── appsforfun │ │ │ └── sam │ │ │ └── collegeapp310 │ │ │ ├── HomeActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── adapters │ │ │ ├── ListAdapter.java │ │ │ └── ViewPagerAdapter.java │ │ │ ├── fragments │ │ │ ├── Friday.java │ │ │ ├── Monday.java │ │ │ ├── Thursday.java │ │ │ ├── Tuesday.java │ │ │ └── Wednesday.java │ │ │ ├── models │ │ │ ├── HandleTimetableData.java │ │ │ └── TimetableModel.java │ │ │ └── views │ │ │ └── FragmentView.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── bottom_bar_margin_top.xml │ │ ├── dialog_btn_next.xml │ │ ├── dialog_btn_previous.xml │ │ ├── ic_add.xml │ │ ├── ic_arrow_back.xml │ │ ├── ic_arrow_forward.xml │ │ ├── ic_cancel.xml │ │ ├── ic_check_circle.xml │ │ ├── ic_delete_sweep.xml │ │ ├── ic_edit.xml │ │ ├── ic_email.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_lock.xml │ │ ├── ic_menu.xml │ │ ├── ic_refresh.xml │ │ ├── login_layout_background.xml │ │ ├── login_logo.jpg │ │ └── signup_button.xml │ │ ├── layout │ │ ├── activity_home.xml │ │ ├── activity_login.xml │ │ ├── dialog_faculty_name.xml │ │ ├── dialog_forgot_password.xml │ │ ├── dialog_hour.xml │ │ ├── dialog_reauth_password.xml │ │ ├── dialog_room_no.xml │ │ ├── dialog_subject_code.xml │ │ ├── dialog_subject_name.xml │ │ ├── dialog_time_from.xml │ │ ├── dialog_time_to.xml │ │ ├── dialog_update_password.xml │ │ ├── fragment_friday.xml │ │ ├── fragment_layout_main.xml │ │ ├── fragment_monday.xml │ │ ├── fragment_thursday.xml │ │ ├── fragment_tuesday.xml │ │ ├── fragment_wednesday.xml │ │ └── item_view.xml │ │ ├── menu │ │ ├── fab_menu.xml │ │ └── home_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ ├── ic_launcher_round.xml │ │ ├── ic_mylogo.xml │ │ └── ic_mylogo_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_mylogo.png │ │ ├── ic_mylogo_foreground.png │ │ └── ic_mylogo_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_mylogo.png │ │ ├── ic_mylogo_foreground.png │ │ └── ic_mylogo_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_mylogo.png │ │ ├── ic_mylogo_foreground.png │ │ └── ic_mylogo_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_mylogo.png │ │ ├── ic_mylogo_foreground.png │ │ └── ic_mylogo_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_mylogo.png │ │ ├── ic_mylogo_foreground.png │ │ └── ic_mylogo_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── ic_mylogo_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── appsforfun │ └── sam │ └── collegeapp310 │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /.idea/assetWizardSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 127 | 128 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimpleTimetableApp 2 | A basic android app to add and display student timetable. 3 | This app uses firebase authentication system and firebase database as backend. 4 | All the timetable data is stored and managed online. 5 | The purpose of this app is to keep our timetable arranged and manage it easily wherever we are. 6 | This app also demonstrates the working concepts of firebase database. 7 | ## Download link 8 | Works on version 5.0+ (Lollipop and above) 9 | [SimpleTimetable.apk](https://drive.google.com/file/d/13UZqbz008D0VBT8JELGkgV3pRt3ceJpR/view?usp=sharing) 10 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.google.gms.google-services' 3 | 4 | android { 5 | compileSdkVersion 28 6 | defaultConfig { 7 | applicationId "com.appsforfun.sam.collegeapp310" 8 | minSdkVersion 21 9 | targetSdkVersion 28 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | productFlavors { 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(include: ['*.jar'], dir: 'libs') 26 | implementation 'com.android.support:appcompat-v7:28.0.0' 27 | implementation 'com.android.support:design:28.0.0' 28 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 29 | implementation 'com.leinardi.android:speed-dial:2.0.0' 30 | implementation 'com.androidadvance:topsnackbar:1.1.1' 31 | implementation 'de.hdodenhof:circleimageview:2.2.0' 32 | //implementation 'com.github.ozodrukh:RippleDrawable:2.0.0' 33 | testImplementation 'junit:junit:4.12' 34 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 35 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 36 | implementation 'com.google.firebase:firebase-auth:16.0.4' 37 | implementation 'com.google.firebase:firebase-database:16.0.1' 38 | implementation 'com.google.firebase:firebase-core:16.0.4' 39 | } 40 | apply plugin: 'com.google.gms.google-services' 41 | -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "871288972151", 4 | "firebase_url": "https://collegeapp310.firebaseio.com", 5 | "project_id": "collegeapp310", 6 | "storage_bucket": "collegeapp310.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:871288972151:android:cc5bb4d43fffe8a3", 12 | "android_client_info": { 13 | "package_name": "com.appsforfun.sam.collegeapp310" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "871288972151-kspv3em88qpv4chdsqrrd5cm63u3ugph.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "com.appsforfun.sam.collegeapp310", 22 | "certificate_hash": "a0b6906801d87d5f38cf6cfeba9fc31994c0b7ad" 23 | } 24 | }, 25 | { 26 | "client_id": "871288972151-r2330l7tpvmr55bkbglugs18a2mhe5tm.apps.googleusercontent.com", 27 | "client_type": 3 28 | } 29 | ], 30 | "api_key": [ 31 | { 32 | "current_key": "AIzaSyDZW4ZyPu34Lq4aGD0orbEZvJFX-ClRanc" 33 | } 34 | ], 35 | "services": { 36 | "analytics_service": { 37 | "status": 1 38 | }, 39 | "appinvite_service": { 40 | "status": 2, 41 | "other_platform_oauth_client": [ 42 | { 43 | "client_id": "871288972151-r2330l7tpvmr55bkbglugs18a2mhe5tm.apps.googleusercontent.com", 44 | "client_type": 3 45 | } 46 | ] 47 | }, 48 | "ads_service": { 49 | "status": 2 50 | } 51 | } 52 | } 53 | ], 54 | "configuration_version": "1" 55 | } -------------------------------------------------------------------------------- /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 22 | -------------------------------------------------------------------------------- /app/release/Simple Timetable.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samuel310/SimpleTimetableApp/78a2d0663f0c9f05f820b47cbf1a3461de39084d/app/release/Simple Timetable.apk -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] -------------------------------------------------------------------------------- /app/release/release/app.aab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samuel310/SimpleTimetableApp/78a2d0663f0c9f05f820b47cbf1a3461de39084d/app/release/release/app.aab -------------------------------------------------------------------------------- /app/src/androidTest/java/com/appsforfun/sam/collegeapp310/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.appsforfun.sam.collegeapp310", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/ic_logo_1-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samuel310/SimpleTimetableApp/78a2d0663f0c9f05f820b47cbf1a3461de39084d/app/src/main/ic_logo_1-web.png -------------------------------------------------------------------------------- /app/src/main/ic_logo_2-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samuel310/SimpleTimetableApp/78a2d0663f0c9f05f820b47cbf1a3461de39084d/app/src/main/ic_logo_2-web.png -------------------------------------------------------------------------------- /app/src/main/ic_mylogo-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samuel310/SimpleTimetableApp/78a2d0663f0c9f05f820b47cbf1a3461de39084d/app/src/main/ic_mylogo-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/HomeActivity.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310; 2 | 3 | import android.app.Dialog; 4 | import android.content.Intent; 5 | import android.support.annotation.NonNull; 6 | import android.support.design.widget.TabLayout; 7 | import android.support.design.widget.TextInputEditText; 8 | import android.support.design.widget.TextInputLayout; 9 | import android.support.v4.content.ContextCompat; 10 | import android.support.v4.view.ViewPager; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.os.Bundle; 13 | import android.support.v7.widget.Toolbar; 14 | import android.text.TextUtils; 15 | import android.view.Menu; 16 | import android.view.MenuItem; 17 | import android.view.View; 18 | import android.widget.ImageButton; 19 | import android.widget.RelativeLayout; 20 | import android.widget.TextView; 21 | import android.widget.Toast; 22 | 23 | import com.androidadvance.topsnackbar.TSnackbar; 24 | import com.appsforfun.sam.collegeapp310.adapters.ViewPagerAdapter; 25 | import com.appsforfun.sam.collegeapp310.fragments.Friday; 26 | import com.appsforfun.sam.collegeapp310.fragments.Monday; 27 | import com.appsforfun.sam.collegeapp310.fragments.Thursday; 28 | import com.appsforfun.sam.collegeapp310.fragments.Tuesday; 29 | import com.appsforfun.sam.collegeapp310.fragments.Wednesday; 30 | import com.google.android.gms.tasks.OnCompleteListener; 31 | import com.google.android.gms.tasks.Task; 32 | import com.google.firebase.auth.AuthCredential; 33 | import com.google.firebase.auth.EmailAuthProvider; 34 | import com.google.firebase.auth.FirebaseAuth; 35 | import com.google.firebase.auth.FirebaseUser; 36 | import com.google.firebase.database.FirebaseDatabase; 37 | 38 | public class HomeActivity extends AppCompatActivity { 39 | 40 | private FirebaseAuth mAuth; 41 | private FirebaseAuth.AuthStateListener mAuthStateListener; 42 | private Toolbar mToolbar; 43 | private TabLayout tabLayout; 44 | private ViewPager viewPager; 45 | private FirebaseDatabase database; 46 | private FirebaseUser user; 47 | private RelativeLayout relativeLayout, relativeLayout1; 48 | private TextView loadingMsg; 49 | 50 | private TextInputEditText reEnterPassword, edtNewPassword, edtReNewPassword, edtOldPassword; 51 | private TextInputLayout til_Pass1, til_Pass2, til_Pass3; 52 | private String rePass, newPass, reNewPass, oldPass; 53 | 54 | @Override 55 | protected void onCreate(Bundle savedInstanceState) { 56 | super.onCreate(savedInstanceState); 57 | setContentView(R.layout.activity_home); 58 | checkUserState(); 59 | mToolbar = findViewById(R.id.toolbar); 60 | setSupportActionBar(mToolbar); 61 | getSupportActionBar(); 62 | viewPager = findViewById(R.id.viewPager); 63 | setupViewPager(viewPager); 64 | tabLayout = findViewById(R.id.tabLayout); 65 | tabLayout.setupWithViewPager(viewPager); 66 | database = FirebaseDatabase.getInstance(); 67 | user = mAuth.getCurrentUser(); 68 | relativeLayout = findViewById(R.id.rl_delete_view); 69 | relativeLayout1 = findViewById(R.id.relativeLayout1); 70 | loadingMsg = findViewById(R.id.label); 71 | } 72 | 73 | private void setupViewPager(ViewPager viewPager){ 74 | ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); 75 | adapter.addFragment(new Monday(), "MON"); 76 | adapter.addFragment(new Tuesday(), "TUE"); 77 | adapter.addFragment(new Wednesday(), "WED"); 78 | adapter.addFragment(new Thursday(), "THU"); 79 | adapter.addFragment(new Friday(), "FRI"); 80 | viewPager.setAdapter(adapter); 81 | } 82 | 83 | @Override 84 | public boolean onCreateOptionsMenu(Menu menu) { 85 | getMenuInflater().inflate(R.menu.home_menu, menu); 86 | return true; 87 | } 88 | 89 | @Override 90 | public boolean onOptionsItemSelected(MenuItem item) { 91 | if (item.getItemId() == R.id.signOut){ 92 | mAuth.signOut(); 93 | return true; 94 | } 95 | else if (item.getItemId() == R.id.deleteAccount){ 96 | iniDeleteAccDialog(); 97 | return true; 98 | } 99 | else if (item.getItemId() == R.id.resetPassword){ 100 | iniResetPassDialog(); 101 | return true; 102 | } 103 | return super.onOptionsItemSelected(item); 104 | } 105 | 106 | private void checkUserState(){ 107 | mAuth = FirebaseAuth.getInstance(); 108 | mAuthStateListener = new FirebaseAuth.AuthStateListener() { 109 | @Override 110 | public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { 111 | FirebaseUser user = firebaseAuth.getCurrentUser(); 112 | if (user == null){ 113 | finish(); 114 | } 115 | } 116 | }; 117 | } 118 | 119 | private void iniDeleteAccDialog(){ 120 | 121 | final Dialog dialog = new Dialog(HomeActivity.this); 122 | dialog.setContentView(R.layout.dialog_reauth_password); 123 | reEnterPassword = dialog.findViewById(R.id.edt_reEnter_password); 124 | til_Pass1 = dialog.findViewById(R.id.til_password); 125 | ImageButton btnNext = dialog.findViewById(R.id.btn_next); 126 | btnNext.setOnClickListener(new View.OnClickListener() { 127 | @Override 128 | public void onClick(View v) { 129 | rePass = reEnterPassword.getText().toString(); 130 | if (!TextUtils.isEmpty(rePass)){ 131 | deleteAccount(rePass); 132 | dialog.dismiss(); 133 | } 134 | else { 135 | til_Pass1.setError("please enter your password"); 136 | } 137 | } 138 | }); 139 | ImageButton btnPrevious = dialog.findViewById(R.id.btn_previous); 140 | btnPrevious.setOnClickListener(new View.OnClickListener() { 141 | @Override 142 | public void onClick(View v) { 143 | rePass = ""; 144 | dialog.dismiss(); 145 | } 146 | }); 147 | dialog.setCanceledOnTouchOutside(false); 148 | dialog.show(); 149 | 150 | } 151 | 152 | private void deleteAccount(String password){ 153 | loadingMsg.setText("Deleting..."); 154 | relativeLayout.setVisibility(View.VISIBLE); 155 | AuthCredential credential = EmailAuthProvider.getCredential(user.getEmail(), password); 156 | mAuth.getCurrentUser().reauthenticate(credential).addOnCompleteListener(new OnCompleteListener() { 157 | @Override 158 | public void onComplete(@NonNull Task task) { 159 | if (task.isSuccessful()){ 160 | user.delete().addOnCompleteListener(new OnCompleteListener() { 161 | @Override 162 | public void onComplete(@NonNull Task task) { 163 | if (!task.isSuccessful()){ 164 | relativeLayout.setVisibility(View.GONE); 165 | showSnackBar(task.getException().getMessage(), android.R.color.holo_red_dark); 166 | } 167 | else { 168 | database.getReference(user.getUid()).removeValue().addOnCompleteListener(new OnCompleteListener() { 169 | @Override 170 | public void onComplete(@NonNull Task task) { 171 | relativeLayout.setVisibility(View.GONE); 172 | } 173 | }); 174 | } 175 | } 176 | }); 177 | } 178 | else { 179 | relativeLayout.setVisibility(View.GONE); 180 | showSnackBar(task.getException().getMessage(), android.R.color.holo_red_dark); 181 | } 182 | } 183 | }); 184 | 185 | } 186 | 187 | private void iniResetPassDialog(){ 188 | final Dialog dialog = new Dialog(HomeActivity.this); 189 | dialog.setContentView(R.layout.dialog_update_password); 190 | edtOldPassword = dialog.findViewById(R.id.edt_old_password); 191 | edtNewPassword = dialog.findViewById(R.id.edt_new_password); 192 | edtReNewPassword = dialog.findViewById(R.id.edt_renew_password); 193 | til_Pass1 = dialog.findViewById(R.id.til_password1); 194 | til_Pass2 = dialog.findViewById(R.id.til_password2); 195 | til_Pass3 = dialog.findViewById(R.id.til_password3); 196 | ImageButton btnNext = dialog.findViewById(R.id.btn_next); 197 | btnNext.setOnClickListener(new View.OnClickListener() { 198 | @Override 199 | public void onClick(View v) { 200 | oldPass = edtOldPassword.getText().toString(); 201 | newPass = edtNewPassword.getText().toString(); 202 | reNewPass = edtReNewPassword.getText().toString(); 203 | if (!TextUtils.isEmpty(newPass) && !TextUtils.isEmpty(reNewPass) && !TextUtils.isEmpty(oldPass)){ 204 | if (newPass.equals(reNewPass)){ 205 | dialog.dismiss(); 206 | resetPassword(reNewPass, oldPass); 207 | } 208 | else { 209 | Toast.makeText(HomeActivity.this, "password incorrect", Toast.LENGTH_SHORT).show(); 210 | } 211 | } 212 | else { 213 | if (TextUtils.isEmpty(newPass)){ 214 | til_Pass2.setError(" "); 215 | } 216 | if (TextUtils.isEmpty(oldPass)){ 217 | til_Pass1.setError(" "); 218 | } 219 | if (TextUtils.isEmpty(reNewPass)){ 220 | til_Pass3.setError(" "); 221 | } 222 | } 223 | } 224 | }); 225 | ImageButton btnPrevious = dialog.findViewById(R.id.btn_previous); 226 | btnPrevious.setOnClickListener(new View.OnClickListener() { 227 | @Override 228 | public void onClick(View v) { 229 | dialog.dismiss(); 230 | } 231 | }); 232 | dialog.setCanceledOnTouchOutside(false); 233 | dialog.show(); 234 | 235 | } 236 | 237 | private void resetPassword(final String passwordNew, String passwordOld){ 238 | loadingMsg.setText("Updating..."); 239 | relativeLayout.setVisibility(View.VISIBLE); 240 | 241 | AuthCredential credential = EmailAuthProvider.getCredential(user.getEmail(), passwordOld); 242 | mAuth.getCurrentUser().reauthenticate(credential).addOnCompleteListener(new OnCompleteListener() { 243 | @Override 244 | public void onComplete(@NonNull Task task) { 245 | if (task.isSuccessful()){ 246 | user.updatePassword(passwordNew).addOnCompleteListener(new OnCompleteListener() { 247 | @Override 248 | public void onComplete(@NonNull Task task) { 249 | if (task.isSuccessful()){ 250 | mAuth.signOut(); 251 | relativeLayout.setVisibility(View.GONE); 252 | } 253 | else { 254 | showSnackBar(task.getException().getMessage(), android.R.color.holo_red_dark); 255 | relativeLayout.setVisibility(View.GONE); 256 | } 257 | } 258 | }); 259 | } 260 | else { 261 | relativeLayout.setVisibility(View.GONE); 262 | showSnackBar(task.getException().getMessage(), android.R.color.holo_red_dark); 263 | } 264 | } 265 | }); 266 | } 267 | 268 | private void showSnackBar(String msg, int color){ 269 | TSnackbar snackbar = TSnackbar.make(relativeLayout1, msg, TSnackbar.LENGTH_LONG); 270 | snackbar.setActionTextColor(ContextCompat.getColor(HomeActivity.this, android.R.color.white)); 271 | View snackView = snackbar.getView(); 272 | snackView.setBackgroundColor(ContextCompat.getColor(HomeActivity.this, R.color.colorPrimaryDark)); 273 | TextView textView = snackView.findViewById(com.androidadvance.topsnackbar.R.id.snackbar_text); 274 | textView.setTextColor(ContextCompat.getColor(HomeActivity.this, color)); 275 | snackbar.show(); 276 | } 277 | 278 | @Override 279 | public void onBackPressed() { 280 | Intent intent = new Intent(HomeActivity.this, LoginActivity.class); 281 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 282 | intent.putExtra("EXIT", true); 283 | startActivity(intent); 284 | } 285 | 286 | @Override 287 | protected void onStart() { 288 | super.onStart(); 289 | mAuth.addAuthStateListener(mAuthStateListener); 290 | } 291 | 292 | @Override 293 | protected void onStop() { 294 | super.onStop(); 295 | if(mAuthStateListener != null){ 296 | mAuth.removeAuthStateListener(mAuthStateListener); 297 | } 298 | } 299 | } 300 | 301 | // TODO: 12-10-2018 logo 302 | // TODO: 12-10-2018 arrange in hour order -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310; 2 | 3 | import android.app.Dialog; 4 | import android.content.Intent; 5 | import android.content.pm.ActivityInfo; 6 | import android.support.annotation.NonNull; 7 | import android.support.design.widget.TextInputEditText; 8 | import android.support.design.widget.TextInputLayout; 9 | import android.support.v4.content.ContextCompat; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.os.Bundle; 12 | import android.text.TextUtils; 13 | import android.view.View; 14 | import android.widget.Button; 15 | import android.widget.ImageButton; 16 | import android.widget.ProgressBar; 17 | import android.widget.RelativeLayout; 18 | import android.widget.TextView; 19 | 20 | import com.androidadvance.topsnackbar.TSnackbar; 21 | import com.google.android.gms.tasks.OnCompleteListener; 22 | import com.google.android.gms.tasks.Task; 23 | import com.google.firebase.auth.AuthResult; 24 | import com.google.firebase.auth.FirebaseAuth; 25 | import com.google.firebase.auth.FirebaseUser; 26 | 27 | public class LoginActivity extends AppCompatActivity { 28 | 29 | private Button login, signup, forgotPass; 30 | private TextInputEditText edtEmail, edtPassword, recoveryEmail; 31 | private TextInputLayout tilPassword; 32 | private FirebaseAuth mAuth; 33 | private FirebaseAuth.AuthStateListener mAuthStateListener; 34 | private ProgressBar progressBar; 35 | private String prEmail; 36 | private RelativeLayout relativeLayout; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 42 | setContentView(R.layout.activity_login); 43 | 44 | checkUserState(); 45 | 46 | if (getIntent().getBooleanExtra("EXIT", false)) 47 | { 48 | finish(); 49 | } 50 | 51 | edtEmail = findViewById(R.id.edt_email); 52 | edtPassword = findViewById(R.id.edt_password); 53 | tilPassword = findViewById(R.id.til_password); 54 | progressBar = findViewById(R.id.login_progress); 55 | relativeLayout = findViewById(R.id.login_layout); 56 | 57 | login = findViewById(R.id.btn_login); 58 | //login.setBackgroundDrawable(getDrawable2(R.drawable.dialog_btn_next)); 59 | //login.setClickable(true); 60 | //login.setOnTouchListener(new DrawableHotspotTouch((LollipopDrawable) login.getBackground())); 61 | login.setOnClickListener(new View.OnClickListener() { 62 | @Override 63 | public void onClick(View v) { 64 | String email = edtEmail.getText().toString().trim(); 65 | String password = edtPassword.getText().toString().trim(); 66 | if (!TextUtils.isEmpty(email) && !TextUtils.isEmpty(password)){ 67 | loginMethod(email,password); 68 | } 69 | else { 70 | if (TextUtils.isEmpty(email)){ 71 | edtEmail.setError("Invalid email"); 72 | } 73 | if (TextUtils.isEmpty(password)){ 74 | tilPassword.setError("Invalid password"); 75 | } 76 | } 77 | } 78 | }); 79 | 80 | signup = findViewById(R.id.btn_signup); 81 | //signup.setBackgroundDrawable(getDrawable2(R.drawable.signup_button)); 82 | //signup.setClickable(true); 83 | //signup.setOnTouchListener(new DrawableHotspotTouch((LollipopDrawable) signup.getBackground())); 84 | signup.setOnClickListener(new View.OnClickListener() { 85 | @Override 86 | public void onClick(View v) { 87 | String email = edtEmail.getText().toString().trim(); 88 | String password = edtPassword.getText().toString().trim(); 89 | if (!TextUtils.isEmpty(email) && !TextUtils.isEmpty(password)){ 90 | signupMethod(email,password); 91 | } 92 | else { 93 | if (TextUtils.isEmpty(email)){ 94 | edtEmail.setError("Invalid email"); 95 | } 96 | if (TextUtils.isEmpty(password)){ 97 | tilPassword.setError("Invalid password"); 98 | } 99 | } 100 | } 101 | }); 102 | 103 | forgotPass = findViewById(R.id.btn_forgotPassword); 104 | forgotPass.setOnClickListener(new View.OnClickListener() { 105 | @Override 106 | public void onClick(View v) { 107 | iniPassRecoveryDialog(); 108 | } 109 | }); 110 | } 111 | 112 | private void checkUserState(){ 113 | mAuth = FirebaseAuth.getInstance(); 114 | mAuthStateListener = new FirebaseAuth.AuthStateListener() { 115 | @Override 116 | public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { 117 | FirebaseUser user = firebaseAuth.getCurrentUser(); 118 | if (user != null){ 119 | Intent intent = new Intent(LoginActivity.this, HomeActivity.class); 120 | startActivity(intent); 121 | } 122 | } 123 | }; 124 | } 125 | 126 | private void loginMethod(String email, String password){ 127 | progressBar.setVisibility(View.VISIBLE); 128 | mAuth.signInWithEmailAndPassword(email,password).addOnCompleteListener(new OnCompleteListener() { 129 | @Override 130 | public void onComplete(@NonNull Task task) { 131 | if (!task.isSuccessful()){ 132 | progressBar.setVisibility(View.GONE); 133 | showSnackBar(task.getException().getMessage(), android.R.color.holo_red_dark); 134 | } 135 | else { 136 | progressBar.setVisibility(View.GONE); 137 | edtEmail.setText(""); 138 | edtPassword.setText(""); 139 | } 140 | } 141 | }); 142 | 143 | 144 | } 145 | 146 | private void signupMethod(String email, String password){ 147 | progressBar.setVisibility(View.VISIBLE); 148 | mAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener() { 149 | @Override 150 | public void onComplete(@NonNull Task task) { 151 | if (!task.isSuccessful()){ 152 | progressBar.setVisibility(View.GONE); 153 | showSnackBar(task.getException().getMessage(), android.R.color.holo_red_dark); 154 | } 155 | else { 156 | progressBar.setVisibility(View.GONE); 157 | edtEmail.setText(""); 158 | edtPassword.setText(""); 159 | } 160 | } 161 | }); 162 | } 163 | 164 | private void iniPassRecoveryDialog(){ 165 | final Dialog dialog = new Dialog(LoginActivity.this); 166 | dialog.setContentView(R.layout.dialog_forgot_password); 167 | recoveryEmail = dialog.findViewById(R.id.edt_recovery_mail); 168 | ImageButton btnNext = dialog.findViewById(R.id.btn_next); 169 | btnNext.setOnClickListener(new View.OnClickListener() { 170 | @Override 171 | public void onClick(View v) { 172 | prEmail = recoveryEmail.getText().toString(); 173 | if (!TextUtils.isEmpty(prEmail)){ 174 | dialog.dismiss(); 175 | sendPasswordRecoveryMail(prEmail); 176 | } 177 | else { 178 | recoveryEmail.setError("enter your email"); 179 | } 180 | } 181 | }); 182 | ImageButton btnPrevious = dialog.findViewById(R.id.btn_previous); 183 | btnPrevious.setOnClickListener(new View.OnClickListener() { 184 | @Override 185 | public void onClick(View v) { 186 | dialog.dismiss(); 187 | } 188 | }); 189 | dialog.setCanceledOnTouchOutside(false); 190 | dialog.show(); 191 | } 192 | 193 | private void sendPasswordRecoveryMail(final String email){ 194 | progressBar.setVisibility(View.VISIBLE); 195 | mAuth.sendPasswordResetEmail(email).addOnCompleteListener(new OnCompleteListener() { 196 | @Override 197 | public void onComplete(@NonNull Task task) { 198 | if (task.isSuccessful()){ 199 | progressBar.setVisibility(View.GONE); 200 | showSnackBar("Password recovery email is sent to email " + email, android.R.color.holo_green_dark); 201 | } 202 | else { 203 | progressBar.setVisibility(View.GONE); 204 | showSnackBar(task.getException().getMessage(), android.R.color.holo_red_dark); 205 | } 206 | } 207 | }); 208 | } 209 | 210 | private void showSnackBar(String msg, int color){ 211 | TSnackbar snackbar = TSnackbar.make(relativeLayout, msg, TSnackbar.LENGTH_LONG); 212 | snackbar.setActionTextColor(ContextCompat.getColor(LoginActivity.this, android.R.color.white)); 213 | View snackView = snackbar.getView(); 214 | snackView.setBackgroundColor(ContextCompat.getColor(LoginActivity.this, R.color.colorPrimaryDark)); 215 | TextView textView = snackView.findViewById(com.androidadvance.topsnackbar.R.id.snackbar_text); 216 | textView.setTextColor(ContextCompat.getColor(LoginActivity.this, color)); 217 | snackbar.show(); 218 | } 219 | 220 | /*public Drawable getDrawable2(int id){ 221 | return LollipopDrawablesCompat.getDrawable(getResources(), id, getTheme()); 222 | }*/ 223 | 224 | @Override 225 | protected void onStart() { 226 | super.onStart(); 227 | mAuth.addAuthStateListener(mAuthStateListener); 228 | } 229 | 230 | @Override 231 | protected void onStop() { 232 | super.onStop(); 233 | if(mAuthStateListener != null){ 234 | mAuth.removeAuthStateListener(mAuthStateListener); 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/adapters/ListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.adapters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.ContextMenu; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import com.appsforfun.sam.collegeapp310.R; 12 | import com.appsforfun.sam.collegeapp310.models.TimetableModel; 13 | 14 | import java.util.List; 15 | 16 | public class ListAdapter extends RecyclerView.Adapter{ 17 | 18 | private List list; 19 | 20 | public ListAdapter(List list){ 21 | this.list = list; 22 | } 23 | 24 | @NonNull 25 | @Override 26 | public ListViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { 27 | return new ListViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_view, viewGroup, false)); 28 | } 29 | 30 | @Override 31 | public void onBindViewHolder(@NonNull final ListViewHolder listViewHolder, int i) { 32 | TimetableModel timetable = list.get(i); 33 | listViewHolder.subName.setText(timetable.subName); 34 | listViewHolder.subHour.setText(timetable.hour + ""); 35 | listViewHolder.subCode.setText(timetable.subCode); 36 | listViewHolder.roomNo.setText(timetable.roomNo); 37 | listViewHolder.facName.setText(timetable.facName); 38 | listViewHolder.time.setText(timetable.time); 39 | listViewHolder.itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { 40 | @Override 41 | public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { 42 | menu.add(listViewHolder.getAdapterPosition(), 0, 0, "Delete"); 43 | } 44 | }); 45 | } 46 | 47 | @Override 48 | public int getItemCount() { 49 | return list.size(); 50 | } 51 | 52 | class ListViewHolder extends RecyclerView.ViewHolder{ 53 | 54 | TextView subName, subHour, subCode, roomNo, facName, time; 55 | 56 | public ListViewHolder(@NonNull View itemView) { 57 | super(itemView); 58 | subName = itemView.findViewById(R.id.tv_subject_name); 59 | subHour = itemView.findViewById(R.id.tv_subject_hour); 60 | subCode = itemView.findViewById(R.id.tv_subject_code); 61 | roomNo = itemView.findViewById(R.id.tv_room_no); 62 | facName = itemView.findViewById(R.id.tv_faculty_name); 63 | time = itemView.findViewById(R.id.tv_time); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/adapters/ViewPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.adapters; 2 | 3 | import android.support.annotation.Nullable; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.app.FragmentPagerAdapter; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class ViewPagerAdapter extends FragmentPagerAdapter { 12 | 13 | private final List mFragmentList = new ArrayList<>(); 14 | private final List mFragmentTitleList = new ArrayList<>(); 15 | 16 | public ViewPagerAdapter(FragmentManager fm) { 17 | super(fm); 18 | } 19 | 20 | @Override 21 | public Fragment getItem(int i) { 22 | return mFragmentList.get(i); 23 | } 24 | 25 | @Override 26 | public int getCount() { 27 | return mFragmentList.size(); 28 | } 29 | 30 | public void addFragment(Fragment fragment, String title){ 31 | mFragmentList.add(fragment); 32 | mFragmentTitleList.add(title); 33 | } 34 | 35 | @Nullable 36 | @Override 37 | public CharSequence getPageTitle(int position) { 38 | return mFragmentTitleList.get(position); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/fragments/Friday.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.appsforfun.sam.collegeapp310.R; 13 | import com.appsforfun.sam.collegeapp310.views.FragmentView; 14 | 15 | public class Friday extends Fragment { 16 | 17 | private FragmentView fragmentView; 18 | 19 | public Friday(){ 20 | } 21 | 22 | @Nullable 23 | @Override 24 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 25 | return inflater.inflate(R.layout.fragment_friday, container, false); 26 | } 27 | 28 | @Override 29 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 30 | super.onViewCreated(view, savedInstanceState); 31 | 32 | fragmentView = new FragmentView(getActivity(), view); 33 | fragmentView.initiateProcess("friday"); 34 | } 35 | 36 | @Override 37 | public boolean onContextItemSelected(MenuItem item) { 38 | if (getUserVisibleHint()) { 39 | switch (item.getItemId()){ 40 | case 0: 41 | fragmentView.getHandleTimetableData().deleteTimetableData(item.getGroupId()); 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/fragments/Monday.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.appsforfun.sam.collegeapp310.R; 13 | import com.appsforfun.sam.collegeapp310.views.FragmentView; 14 | 15 | 16 | public class Monday extends Fragment { 17 | 18 | private FragmentView fragmentView; 19 | 20 | public Monday(){ 21 | } 22 | 23 | @Nullable 24 | @Override 25 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 26 | return inflater.inflate(R.layout.fragment_monday, container, false); 27 | } 28 | 29 | @Override 30 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 31 | super.onViewCreated(view, savedInstanceState); 32 | 33 | fragmentView = new FragmentView(getActivity(), view); 34 | fragmentView.initiateProcess("monday"); 35 | 36 | 37 | 38 | } 39 | 40 | @Override 41 | public boolean onContextItemSelected(MenuItem item) { 42 | if (getUserVisibleHint()) { 43 | switch (item.getItemId()){ 44 | case 0: 45 | fragmentView.getHandleTimetableData().deleteTimetableData(item.getGroupId()); 46 | return true; 47 | } 48 | } 49 | return false; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/fragments/Thursday.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.appsforfun.sam.collegeapp310.R; 13 | import com.appsforfun.sam.collegeapp310.views.FragmentView; 14 | 15 | public class Thursday extends Fragment { 16 | 17 | private FragmentView fragmentView; 18 | 19 | public Thursday(){ 20 | } 21 | 22 | @Nullable 23 | @Override 24 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 25 | return inflater.inflate(R.layout.fragment_thursday, container, false); 26 | } 27 | 28 | @Override 29 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 30 | super.onViewCreated(view, savedInstanceState); 31 | 32 | fragmentView = new FragmentView(getActivity(), view); 33 | fragmentView.initiateProcess("thursday"); 34 | } 35 | 36 | @Override 37 | public boolean onContextItemSelected(MenuItem item) { 38 | if (getUserVisibleHint()) { 39 | switch (item.getItemId()){ 40 | case 0: 41 | fragmentView.getHandleTimetableData().deleteTimetableData(item.getGroupId()); 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/fragments/Tuesday.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.appsforfun.sam.collegeapp310.R; 13 | import com.appsforfun.sam.collegeapp310.views.FragmentView; 14 | 15 | public class Tuesday extends Fragment { 16 | 17 | private FragmentView fragmentView; 18 | 19 | public Tuesday(){ 20 | } 21 | 22 | @Nullable 23 | @Override 24 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 25 | return inflater.inflate(R.layout.fragment_tuesday, container, false); 26 | } 27 | 28 | @Override 29 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 30 | super.onViewCreated(view, savedInstanceState); 31 | 32 | fragmentView = new FragmentView(getActivity(), view); 33 | fragmentView.initiateProcess("tuesday"); 34 | } 35 | 36 | @Override 37 | public boolean onContextItemSelected(MenuItem item) { 38 | if (getUserVisibleHint()) { 39 | switch (item.getItemId()){ 40 | case 0: 41 | fragmentView.getHandleTimetableData().deleteTimetableData(item.getGroupId()); 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/fragments/Wednesday.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.appsforfun.sam.collegeapp310.R; 13 | import com.appsforfun.sam.collegeapp310.views.FragmentView; 14 | 15 | public class Wednesday extends Fragment { 16 | 17 | private FragmentView fragmentView; 18 | 19 | public Wednesday(){ 20 | } 21 | 22 | @Nullable 23 | @Override 24 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 25 | return inflater.inflate(R.layout.fragment_wednesday, container, false); 26 | } 27 | 28 | @Override 29 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 30 | super.onViewCreated(view, savedInstanceState); 31 | 32 | fragmentView = new FragmentView(getActivity(), view); 33 | fragmentView.initiateProcess("wednesday"); 34 | } 35 | 36 | @Override 37 | public boolean onContextItemSelected(MenuItem item) { 38 | if (getUserVisibleHint()) { 39 | switch (item.getItemId()){ 40 | case 0: 41 | fragmentView.getHandleTimetableData().deleteTimetableData(item.getGroupId()); 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/models/HandleTimetableData.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.models; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.v4.widget.SwipeRefreshLayout; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.ProgressBar; 10 | import android.widget.TextView; 11 | import android.widget.Toast; 12 | 13 | import com.appsforfun.sam.collegeapp310.adapters.ListAdapter; 14 | import com.google.android.gms.tasks.OnCompleteListener; 15 | import com.google.android.gms.tasks.Task; 16 | import com.google.firebase.database.ChildEventListener; 17 | import com.google.firebase.database.DataSnapshot; 18 | import com.google.firebase.database.DatabaseError; 19 | import com.google.firebase.database.DatabaseReference; 20 | import com.google.firebase.database.ValueEventListener; 21 | 22 | import java.util.Collections; 23 | import java.util.Comparator; 24 | import java.util.List; 25 | 26 | import static android.content.ContentValues.TAG; 27 | 28 | public class HandleTimetableData { 29 | 30 | private Context context; 31 | private ProgressBar mProgress; 32 | private DatabaseReference reference; 33 | private List result; 34 | private ListAdapter adapter; 35 | private TextView emptyText; 36 | private SwipeRefreshLayout mSwipeRefreshLayout; 37 | private RecyclerView recyclerView; 38 | 39 | private void sortData(){ 40 | if (!result.isEmpty()){ 41 | Collections.sort(result, new SortByHour()); 42 | } 43 | } 44 | 45 | private int getItemIndex(TimetableModel user){ 46 | int index = -1; 47 | for (int i=0; i result, ListAdapter adapter){ 68 | this.context = context; 69 | this.mSwipeRefreshLayout = mSwipeRefreshLayout; 70 | this.recyclerView = recyclerView; 71 | this.emptyText = emptyText; 72 | this.mProgress = mProgress; 73 | this.reference = reference; 74 | this.result = result; 75 | this.adapter = adapter; 76 | } 77 | 78 | public void addTimetableData(int hour, String subName, String subCode, String facName, String roomNo, String time){ 79 | mProgress.setVisibility(View.VISIBLE); 80 | String key = reference.push().getKey(); 81 | TimetableModel timetableModel = new TimetableModel(hour, subName, subCode, facName, roomNo, key, time); 82 | reference.child(key).setValue(timetableModel).addOnCompleteListener(new OnCompleteListener() { 83 | @Override 84 | public void onComplete(@NonNull Task task) { 85 | if (task.isSuccessful()){ 86 | mProgress.setVisibility(View.GONE); 87 | refresh(); 88 | } 89 | else { 90 | Toast.makeText(context, task.getException().getMessage(), Toast.LENGTH_SHORT).show(); 91 | mProgress.setVisibility(View.GONE); 92 | } 93 | } 94 | }); 95 | } 96 | 97 | public void deleteTimetableData(int position){ 98 | mProgress.setVisibility(View.VISIBLE); 99 | reference.child(result.get(position).key).removeValue().addOnCompleteListener(new OnCompleteListener() { 100 | @Override 101 | public void onComplete(@NonNull Task task) { 102 | if (task.isSuccessful()){ 103 | mProgress.setVisibility(View.GONE); 104 | } 105 | else { 106 | Toast.makeText(context, task.getException().getMessage(), Toast.LENGTH_SHORT).show(); 107 | mProgress.setVisibility(View.GONE); 108 | } 109 | } 110 | }); 111 | } 112 | 113 | public void updateList(){ 114 | mProgress.setVisibility(View.VISIBLE); 115 | reference.addListenerForSingleValueEvent(new ValueEventListener() { 116 | @Override 117 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 118 | mProgress.setVisibility(View.GONE); 119 | } 120 | 121 | @Override 122 | public void onCancelled(@NonNull DatabaseError databaseError) { 123 | mProgress.setVisibility(View.GONE); 124 | } 125 | }); 126 | 127 | reference.addChildEventListener(new ChildEventListener() { 128 | @Override 129 | public void onChildAdded(DataSnapshot dataSnapshot, String s) { 130 | result.add(dataSnapshot.getValue(TimetableModel.class)); 131 | sortData(); 132 | adapter.notifyDataSetChanged(); 133 | checkIfEmpty(); 134 | } 135 | 136 | @Override 137 | public void onChildChanged(DataSnapshot dataSnapshot, String s) { 138 | TimetableModel model = dataSnapshot.getValue(TimetableModel.class); 139 | int index = getItemIndex(model); 140 | result.set(index, model); 141 | adapter.notifyItemChanged(index); 142 | } 143 | 144 | @Override 145 | public void onChildRemoved(DataSnapshot dataSnapshot) { 146 | TimetableModel model = dataSnapshot.getValue(TimetableModel.class); 147 | int index = getItemIndex(model); 148 | if (index > -1){ 149 | result.remove(index); 150 | sortData(); 151 | adapter.notifyItemRemoved(index); 152 | } 153 | checkIfEmpty(); 154 | } 155 | 156 | @Override 157 | public void onChildMoved(DataSnapshot dataSnapshot, String s) { 158 | 159 | } 160 | 161 | @Override 162 | public void onCancelled(DatabaseError databaseError) { 163 | 164 | } 165 | }); 166 | } 167 | 168 | public void refresh(){ 169 | result.clear(); 170 | if (result.isEmpty()){ 171 | updateList(); 172 | } 173 | if (mSwipeRefreshLayout.isRefreshing()){ 174 | mSwipeRefreshLayout.setRefreshing(false); 175 | } 176 | } 177 | 178 | public void deleteAll(){ 179 | mProgress.setVisibility(View.VISIBLE); 180 | reference.removeValue().addOnCompleteListener(new OnCompleteListener() { 181 | @Override 182 | public void onComplete(@NonNull Task task) { 183 | if (task.isSuccessful()){ 184 | result.clear(); 185 | mProgress.setVisibility(View.GONE); 186 | checkIfEmpty(); 187 | } 188 | else { 189 | Toast.makeText(context, task.getException().getMessage(), Toast.LENGTH_SHORT).show(); 190 | mProgress.setVisibility(View.GONE); 191 | } 192 | } 193 | }); 194 | } 195 | 196 | class SortByHour implements Comparator 197 | { 198 | public int compare(TimetableModel a, TimetableModel b) 199 | { 200 | return a.hour - b.hour; 201 | } 202 | } 203 | 204 | } 205 | 206 | 207 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/models/TimetableModel.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.models; 2 | 3 | public class TimetableModel { 4 | public int hour; 5 | public String subName, subCode, facName, roomNo, key, time; 6 | public TimetableModel(){ 7 | 8 | } 9 | public TimetableModel(int hour, String subName, String subCode, String facName, String roomNo, String key, String time) { 10 | this.hour = hour; 11 | this.subName = subName; 12 | this.subCode = subCode; 13 | this.facName = facName; 14 | this.roomNo = roomNo; 15 | this.key = key; 16 | this.time = time; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/appsforfun/sam/collegeapp310/views/FragmentView.java: -------------------------------------------------------------------------------- 1 | package com.appsforfun.sam.collegeapp310.views; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.support.v4.content.ContextCompat; 7 | import android.support.v4.widget.SwipeRefreshLayout; 8 | import android.support.v7.app.AlertDialog; 9 | import android.support.v7.widget.LinearLayoutManager; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.text.TextUtils; 12 | import android.view.View; 13 | import android.widget.EditText; 14 | import android.widget.ImageButton; 15 | import android.widget.NumberPicker; 16 | import android.widget.ProgressBar; 17 | import android.widget.TextView; 18 | import android.widget.TimePicker; 19 | import android.widget.Toast; 20 | 21 | import com.appsforfun.sam.collegeapp310.R; 22 | import com.appsforfun.sam.collegeapp310.adapters.ListAdapter; 23 | import com.appsforfun.sam.collegeapp310.models.HandleTimetableData; 24 | import com.appsforfun.sam.collegeapp310.models.TimetableModel; 25 | import com.google.firebase.auth.FirebaseAuth; 26 | import com.google.firebase.auth.FirebaseUser; 27 | import com.google.firebase.database.DatabaseReference; 28 | import com.google.firebase.database.FirebaseDatabase; 29 | import com.leinardi.android.speeddial.SpeedDialActionItem; 30 | import com.leinardi.android.speeddial.SpeedDialView; 31 | 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | public class FragmentView { 36 | 37 | private Context context; 38 | private View view; 39 | private RecyclerView recyclerView; 40 | private ListAdapter adapter; 41 | private List result; 42 | private SwipeRefreshLayout mSwipeRefreshLayout; 43 | private FirebaseDatabase database; 44 | private DatabaseReference reference; 45 | private ProgressBar mProgress; 46 | private TextView emptyText; 47 | private HandleTimetableData handleTimetableData; 48 | 49 | private int hour; 50 | private String subName, subCode, facName, roomNo, timeFrom, timeTo; 51 | private EditText sName, sCode, fName, rNo; 52 | private TimePicker timePicker; 53 | 54 | public FragmentView(Context context, View view){ 55 | this.context = context; 56 | this.view = view; 57 | } 58 | 59 | public void initiateProcess(String day){ 60 | FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); 61 | database = FirebaseDatabase.getInstance(); 62 | reference = database.getReference(user.getUid()).child(day); 63 | 64 | TextView userEmail = view.findViewById(R.id.tv_acc_email); 65 | userEmail.setText(user.getEmail()); 66 | 67 | result = new ArrayList<>(); 68 | mProgress = view.findViewById(R.id.mProgressBar); 69 | emptyText = view.findViewById(R.id.tv_emptyText); 70 | 71 | iniRecyclerView(); 72 | iniFABs(); 73 | 74 | handleTimetableData = new HandleTimetableData(context, mSwipeRefreshLayout, recyclerView, emptyText, mProgress, reference, result, adapter); 75 | handleTimetableData.updateList(); 76 | } 77 | 78 | public HandleTimetableData getHandleTimetableData() { 79 | return handleTimetableData; 80 | } 81 | 82 | private void iniRecyclerView(){ 83 | recyclerView = view.findViewById(R.id.mRecyclerView); 84 | recyclerView.setHasFixedSize(true); 85 | LinearLayoutManager llm = new LinearLayoutManager(context); 86 | llm.setOrientation(LinearLayoutManager.VERTICAL); 87 | recyclerView.setLayoutManager(llm); 88 | adapter = new ListAdapter(result); 89 | recyclerView.setAdapter(adapter); 90 | 91 | mSwipeRefreshLayout = view.findViewById(R.id.mSwipeRefreshLayout); 92 | mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 93 | @Override 94 | public void onRefresh() { 95 | handleTimetableData.refresh(); 96 | } 97 | }); 98 | mSwipeRefreshLayout.setColorSchemeResources( 99 | android.R.color.holo_green_light, 100 | android.R.color.holo_orange_light, 101 | android.R.color.holo_red_light); 102 | } 103 | 104 | private void iniFABs(){ 105 | SpeedDialView sdv = view.findViewById(R.id.mSpeedDialView); 106 | SpeedDialActionItem item1 = new SpeedDialActionItem.Builder(R.id.addData_fab, R.drawable.ic_edit) 107 | .setFabBackgroundColor(ContextCompat.getColor(context, android.R.color.white)) 108 | .setLabel("Add") 109 | .setLabelClickable(true) 110 | .create(); 111 | SpeedDialActionItem item2 = new SpeedDialActionItem.Builder(R.id.refresh_fab, R.drawable.ic_refresh) 112 | .setFabBackgroundColor(ContextCompat.getColor(context, android.R.color.white)) 113 | .setLabel("Refresh") 114 | .setLabelClickable(true) 115 | .create(); 116 | SpeedDialActionItem item3 = new SpeedDialActionItem.Builder(R.id.deleteAll_fab, R.drawable.ic_delete_sweep) 117 | .setFabBackgroundColor(ContextCompat.getColor(context, android.R.color.white)) 118 | .setLabel("Delete all") 119 | .setLabelClickable(true) 120 | .create(); 121 | 122 | 123 | sdv.addActionItem(item1,0); 124 | sdv.addActionItem(item2,1); 125 | sdv.addActionItem(item3,2); 126 | 127 | 128 | sdv.setOnActionSelectedListener(new SpeedDialView.OnActionSelectedListener() { 129 | @Override 130 | public boolean onActionSelected(SpeedDialActionItem actionItem) { 131 | switch (actionItem.getId()){ 132 | case R.id.addData_fab: 133 | initiateDialog1(); 134 | return false; 135 | case R.id.refresh_fab: 136 | handleTimetableData.refresh(); 137 | return false; 138 | case R.id.deleteAll_fab: 139 | iniDeleteAllDialog(); 140 | return false; 141 | default: 142 | return false; 143 | } 144 | } 145 | }); 146 | } 147 | 148 | private void initiateDialog1(){ 149 | final Dialog dialog = new Dialog(context); 150 | dialog.setContentView(R.layout.dialog_hour); 151 | NumberPicker numberPicker = dialog.findViewById(R.id.hour_picker); 152 | numberPicker.setMinValue(1); 153 | numberPicker.setMaxValue(10); 154 | numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { 155 | @Override 156 | public void onValueChange(NumberPicker picker, int oldVal, int newVal) { 157 | hour = picker.getValue(); 158 | } 159 | }); 160 | ImageButton btnNext = dialog.findViewById(R.id.btn_next); 161 | btnNext.setOnClickListener(new View.OnClickListener() { 162 | @Override 163 | public void onClick(View v) { 164 | if (hour > 0){ 165 | boolean valid = true; 166 | for (int i=0; i 12) { 392 | hr -= 12; 393 | timeSet = "PM"; 394 | } else if (hr == 0) { 395 | hr += 12; 396 | timeSet = "AM"; 397 | } else if (hr == 12){ 398 | timeSet = "PM"; 399 | }else{ 400 | timeSet = "AM"; 401 | } 402 | 403 | String minSet = ""; 404 | if (min < 10){ 405 | minSet = "0" + min ; 406 | } 407 | else{ 408 | minSet = String.valueOf(min); 409 | } 410 | 411 | String aTime = new StringBuilder().append(hr).append(':').append(minSet ).append(" ").append(timeSet).toString(); 412 | return aTime; 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bottom_bar_margin_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog_btn_next.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog_btn_previous.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_forward.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cancel.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check_circle.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_sweep.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_edit.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_email.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lock.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/login_layout_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/login_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samuel310/SimpleTimetableApp/78a2d0663f0c9f05f820b47cbf1a3461de39084d/app/src/main/res/drawable/login_logo.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/signup_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 44 | 45 | 46 | 47 | 53 | 54 | 61 | 62 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 20 | 21 | 28 | 29 | 36 | 37 | 45 | 46 | 54 | 55 | 64 | 65 | 72 | 73 | 80 | 81 | 82 | 83 |