diff --git a/WRSD2/.gitignore b/WRSD2/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/WRSD2/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/WRSD2/.idea/.gitignore b/WRSD2/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/WRSD2/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/WRSD2/.idea/.name b/WRSD2/.idea/.name new file mode 100644 index 0000000..a119e3a --- /dev/null +++ b/WRSD2/.idea/.name @@ -0,0 +1 @@ +WRSD \ No newline at end of file diff --git a/WRSD2/.idea/compiler.xml b/WRSD2/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/WRSD2/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/WRSD2/.idea/deploymentTargetDropDown.xml b/WRSD2/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..2336d7b --- /dev/null +++ b/WRSD2/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WRSD2/.idea/gradle.xml b/WRSD2/.idea/gradle.xml new file mode 100644 index 0000000..a2d7c21 --- /dev/null +++ b/WRSD2/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/WRSD2/.idea/misc.xml b/WRSD2/.idea/misc.xml new file mode 100644 index 0000000..bdd9278 --- /dev/null +++ b/WRSD2/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/WRSD2/.idea/vcs.xml b/WRSD2/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/WRSD2/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/WRSD2/app/.gitignore b/WRSD2/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/WRSD2/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/WRSD2/app/build.gradle b/WRSD2/app/build.gradle new file mode 100644 index 0000000..3f148a4 --- /dev/null +++ b/WRSD2/app/build.gradle @@ -0,0 +1,58 @@ +plugins { + id 'com.android.application' + id 'com.google.gms.google-services' +} + +android { + namespace 'com.example.wrsd' + compileSdk 32 + + defaultConfig { + applicationId "com.example.wrsd" + minSdk 21 + targetSdk 32 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding true + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'com.google.android.material:material:1.5.0' + implementation 'androidx.annotation:annotation:1.3.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' + implementation 'androidx.navigation:navigation-fragment:2.4.1' + implementation 'androidx.navigation:navigation-ui:2.4.1' + implementation 'com.google.firebase:firebase-database:20.1.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + implementation platform('com.google.firebase:firebase-bom:31.1.0') + implementation 'com.google.firebase:firebase-analytics' + implementation 'com.google.firebase:firebase-auth' + implementation 'com.google.firebase:firebase-firestore' + implementation "androidx.cardview:cardview:1.0.0" + implementation 'de.hdodenhof:circleimageview:3.1.0' +} + +apply plugin: 'com.google.gms.google-services' diff --git a/WRSD2/app/google-services.json b/WRSD2/app/google-services.json new file mode 100644 index 0000000..19424da --- /dev/null +++ b/WRSD2/app/google-services.json @@ -0,0 +1,40 @@ +{ + "project_info": { + "project_number": "364206717870", + "firebase_url": "https://wrsd-fabbb-default-rtdb.firebaseio.com", + "project_id": "wrsd-fabbb", + "storage_bucket": "wrsd-fabbb.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:364206717870:android:0f08fe100fcadbc1f9e63f", + "android_client_info": { + "package_name": "com.example.wrsd" + } + }, + "oauth_client": [ + { + "client_id": "364206717870-61ec89v3jg1aro8k8j2ihk99ep1gkkan.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyA9wUpzMLm7YGR_eyfwe3PRc4kC1n2DQM8" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "364206717870-61ec89v3jg1aro8k8j2ihk99ep1gkkan.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/WRSD2/app/proguard-rules.pro b/WRSD2/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/WRSD2/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/WRSD2/app/src/androidTest/java/com/example/wrsd/ExampleInstrumentedTest.java b/WRSD2/app/src/androidTest/java/com/example/wrsd/ExampleInstrumentedTest.java new file mode 100644 index 0000000..a5f18ba --- /dev/null +++ b/WRSD2/app/src/androidTest/java/com/example/wrsd/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example.wrsd; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.example.wrsd", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/AndroidManifest.xml b/WRSD2/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8993dcf --- /dev/null +++ b/WRSD2/app/src/main/AndroidManifest.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/MainActivity.java b/WRSD2/app/src/main/java/com/example/wrsd/MainActivity.java new file mode 100644 index 0000000..2a2c04d --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/MainActivity.java @@ -0,0 +1,44 @@ +package com.example.wrsd; + +import android.os.Bundle; + +import com.google.android.material.snackbar.Snackbar; + +import androidx.appcompat.app.AppCompatActivity; + +import android.view.View; + +import androidx.navigation.NavController; +import androidx.navigation.Navigation; +import androidx.navigation.ui.AppBarConfiguration; +import androidx.navigation.ui.NavigationUI; + +import com.example.wrsd.databinding.ActivityMainBinding; + +public class MainActivity extends AppCompatActivity { + + private AppBarConfiguration appBarConfiguration; + private ActivityMainBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + setSupportActionBar(binding.toolbar); + + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); + appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build(); + NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); + + } + + @Override + public boolean onSupportNavigateUp() { + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); + return NavigationUI.navigateUp(navController, appBarConfiguration) + || super.onSupportNavigateUp(); + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/MainActivity2.java b/WRSD2/app/src/main/java/com/example/wrsd/MainActivity2.java new file mode 100644 index 0000000..de2abc2 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/MainActivity2.java @@ -0,0 +1,20 @@ +package com.example.wrsd; + +import androidx.appcompat.app.AppCompatActivity; +import android.os.Bundle; + +import com.google.firebase.auth.FirebaseAuth; + +public class MainActivity2 extends AppCompatActivity { + + FirebaseAuth mAuth; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_main2); + + mAuth = FirebaseAuth.getInstance(); + + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/RegisterUser.java b/WRSD2/app/src/main/java/com/example/wrsd/RegisterUser.java new file mode 100644 index 0000000..599dacf --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/RegisterUser.java @@ -0,0 +1,125 @@ +package com.example.wrsd; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.util.Patterns; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.Toast; + +import com.example.wrsd.ui.login.LoginActivity; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.FirebaseDatabase; + +import java.io.FileInputStream; +import java.util.regex.Pattern; + +import kotlin.text.Typography; + +public class RegisterUser extends AppCompatActivity{ + + private FirebaseAuth mAuth; + private EditText editTextFirstName, editTextLastName, editTextEmail, editTextPassword; + private ProgressBar progressBar; + private Button registerUser; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register_user); + + mAuth = FirebaseAuth.getInstance(); + + editTextFirstName = (EditText) findViewById(R.id.firstName); + editTextLastName = (EditText) findViewById(R.id.lastname); + editTextEmail = (EditText) findViewById(R.id.email); + editTextPassword = (EditText) findViewById(R.id.newpassword); + progressBar = (ProgressBar) findViewById(R.id.loadingReg); + registerUser = (Button) findViewById(R.id.registerbutton); + + registerUser.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View v){ + registerUser(); + } + }); + + } + + + private void nameValidation() { + + } + + private void registerUser() { + String email = editTextEmail.getText().toString().trim(); + String firstname = editTextFirstName.getText().toString().trim(); + String lastname = editTextLastName.getText().toString().trim(); + String password = editTextPassword.getText().toString().trim(); + + if (firstname.isEmpty()) { + editTextFirstName.setError("Podaj swoje imię!"); + editTextFirstName.requestFocus(); + return; + } + if (lastname.isEmpty()) { + editTextLastName.setError("Podaj swoje nazwisko!"); + editTextLastName.requestFocus(); + return; + } + if (email.isEmpty()) { + editTextEmail.setError("Podaj swój email!"); + editTextEmail.requestFocus(); + return; + } else if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) { + editTextEmail.setError("Podaj prawidłowy email!"); + editTextEmail.requestFocus(); + return; + } + if (password.isEmpty()) { + editTextPassword.setError("Podaj swoje hasło!"); + editTextPassword.requestFocus(); + return; + } else if (password.length() <= 5) { + editTextPassword.setError("Hasło musi mieć więcej niż 5 znaków!"); + editTextPassword.requestFocus(); + return; + } + + progressBar.setVisibility(View.VISIBLE); + mAuth.createUserWithEmailAndPassword(email, password).addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(AuthResult authResult) { + Toast.makeText(getApplicationContext(), "Użytkownik zarejestrowany", Toast.LENGTH_LONG).show(); + Login(); + + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Toast.makeText(getApplicationContext(), "Rejestracja nie powiodła się. Spróbuj ponownie", Toast.LENGTH_LONG).show(); + progressBar.setVisibility(View.GONE); + } + }); + + } + + public void Login() { + Intent intent = new Intent(this, LoginActivity.class); + startActivity(intent); + } + +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/Second2Fragment.java b/WRSD2/app/src/main/java/com/example/wrsd/Second2Fragment.java new file mode 100644 index 0000000..6e8f9ee --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/Second2Fragment.java @@ -0,0 +1,47 @@ +package com.example.wrsd; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.navigation.fragment.NavHostFragment; + +import com.example.wrsd.databinding.FragmentSecond2Binding; + +public class Second2Fragment extends Fragment { + + private FragmentSecond2Binding binding; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState + ) { + + binding = FragmentSecond2Binding.inflate(inflater, container, false); + return binding.getRoot(); + + } + + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + binding.buttonSecond.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + NavHostFragment.findNavController(Second2Fragment.this) + .navigate(R.id.action_Second2Fragment_to_First2Fragment); + } + }); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } + +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/SecondFragment.java b/WRSD2/app/src/main/java/com/example/wrsd/SecondFragment.java new file mode 100644 index 0000000..b7b55da --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/SecondFragment.java @@ -0,0 +1,47 @@ +package com.example.wrsd; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.navigation.fragment.NavHostFragment; + +import com.example.wrsd.databinding.FragmentSecondBinding; + +public class SecondFragment extends Fragment { + + private FragmentSecondBinding binding; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState + ) { + + binding = FragmentSecondBinding.inflate(inflater, container, false); + return binding.getRoot(); + + } + + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + binding.buttonSecond.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + NavHostFragment.findNavController(SecondFragment.this) + .navigate(R.id.action_SecondFragment_to_FirstFragment); + } + }); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } + +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/User.java b/WRSD2/app/src/main/java/com/example/wrsd/User.java new file mode 100644 index 0000000..dbc01f5 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/User.java @@ -0,0 +1,16 @@ +package com.example.wrsd; + +public class User { + public String firstName, lastName, email; + + public User(){ + + } + + public User(String firstName, String lastName, String email){ + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + } + +} diff --git a/WRSD2/app/src/main/java/com/example/wrsd/data/LoginDataSource.java b/WRSD2/app/src/main/java/com/example/wrsd/data/LoginDataSource.java new file mode 100644 index 0000000..2c90122 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/data/LoginDataSource.java @@ -0,0 +1,29 @@ +package com.example.wrsd.data; + +import com.example.wrsd.data.model.LoggedInUser; + +import java.io.IOException; + +/** + * Class that handles authentication w/ login credentials and retrieves user information. + */ +public class LoginDataSource { + + public Result login(String username, String password) { + + try { + // TODO: handle loggedInUser authentication + LoggedInUser fakeUser = + new LoggedInUser( + java.util.UUID.randomUUID().toString(), + username); + return new Result.Success<>(fakeUser); + } catch (Exception e) { + return new Result.Error(new IOException("Error logging in", e)); + } + } + + public void logout() { + // TODO: revoke authentication + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/data/LoginRepository.java b/WRSD2/app/src/main/java/com/example/wrsd/data/LoginRepository.java new file mode 100644 index 0000000..06e4be3 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/data/LoginRepository.java @@ -0,0 +1,54 @@ +package com.example.wrsd.data; + +import com.example.wrsd.data.model.LoggedInUser; + +/** + * Class that requests authentication and user information from the remote data source and + * maintains an in-memory cache of login status and user credentials information. + */ +public class LoginRepository { + + private static volatile LoginRepository instance; + + private LoginDataSource dataSource; + + // If user credentials will be cached in local storage, it is recommended it be encrypted + // @see https://developer.android.com/training/articles/keystore + private LoggedInUser user = null; + + // private constructor : singleton access + private LoginRepository(LoginDataSource dataSource) { + this.dataSource = dataSource; + } + + public static LoginRepository getInstance(LoginDataSource dataSource) { + if (instance == null) { + instance = new LoginRepository(dataSource); + } + return instance; + } + + public boolean isLoggedIn() { + return user != null; + } + + public void logout() { + user = null; + dataSource.logout(); + } + + private void setLoggedInUser(LoggedInUser user) { + this.user = user; + // If user credentials will be cached in local storage, it is recommended it be encrypted + // @see https://developer.android.com/training/articles/keystore + } + + public Result login(String username, String password) { + // handle login + Result result = dataSource.login(username, password); + if (result instanceof Result.Success) { + setLoggedInUser(((Result.Success) result).getData()); + } + return result; + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/data/Result.java b/WRSD2/app/src/main/java/com/example/wrsd/data/Result.java new file mode 100644 index 0000000..81bccbd --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/data/Result.java @@ -0,0 +1,55 @@ +package com.example.wrsd.data; + +import android.content.Intent; + +import com.example.wrsd.MainActivity; + +/** + * A generic class that holds a result success w/ data or an error exception. + */ +public class Result { + // hide the private constructor to limit subclass types (Success, Error) + private Result() { + } + + @Override + public String toString() { + if (this instanceof Result.Success) { + Result.Success success = (Result.Success) this; + return "Success[data=" + success.getData().toString() + "]"; + } else if (this instanceof Result.Error) { + Result.Error error = (Result.Error) this; + return "Error[exception=" + error.getError().toString() + "]"; + } + return ""; + } + + // Success sub-class + public final static class Success extends Result { + private T data; + + public Success(T data) { + this.data = data; + } + + public T getData() { + return this.data; + } + + + } + + + // Error sub-class + public final static class Error extends Result { + private Exception error; + + public Error(Exception error) { + this.error = error; + } + + public Exception getError() { + return this.error; + } + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/data/model/LoggedInUser.java b/WRSD2/app/src/main/java/com/example/wrsd/data/model/LoggedInUser.java new file mode 100644 index 0000000..44024a7 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/data/model/LoggedInUser.java @@ -0,0 +1,23 @@ +package com.example.wrsd.data.model; + +/** + * Data class that captures user information for logged in users retrieved from LoginRepository + */ +public class LoggedInUser { + + private String userId; + private String displayName; + + public LoggedInUser(String userId, String displayName) { + this.userId = userId; + this.displayName = displayName; + } + + public String getUserId() { + return userId; + } + + public String getDisplayName() { + return displayName; + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoggedInUserView.java b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoggedInUserView.java new file mode 100644 index 0000000..0e8517b --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoggedInUserView.java @@ -0,0 +1,17 @@ +package com.example.wrsd.ui.login; + +/** + * Class exposing authenticated user details to the UI. + */ +class LoggedInUserView { + private String displayName; + //... other data fields that may be accessible to the UI + + LoggedInUserView(String displayName) { + this.displayName = displayName; + } + + String getDisplayName() { + return displayName; + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginActivity.java b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginActivity.java new file mode 100644 index 0000000..dbf3469 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginActivity.java @@ -0,0 +1,209 @@ +package com.example.wrsd.ui.login; + +import android.app.Activity; + +import androidx.annotation.NonNull; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; + +import android.content.Intent; +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.AppCompatActivity; + +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.example.wrsd.MainActivity; +import com.example.wrsd.MainActivity2; +import com.example.wrsd.R; +import com.example.wrsd.RegisterUser; +import com.example.wrsd.databinding.ActivityLoginBinding; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +public class LoginActivity extends AppCompatActivity { + + private LoginViewModel loginViewModel; + private ActivityLoginBinding binding; + + private Button login_button; + private TextView register; + FirebaseAuth mAuth; + FirebaseUser mUser; + private EditText usernameEditText2; + private EditText passwordEditText2; + private ProgressBar progressBar; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + binding = ActivityLoginBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + loginViewModel = new ViewModelProvider(this, new LoginViewModelFactory()) + .get(LoginViewModel.class); + + + final Button loginButton = binding.login; + final EditText usernameEditText = binding.username; + final EditText passwordEditText = binding.password; + + mAuth = FirebaseAuth.getInstance(); + mUser = mAuth.getCurrentUser(); + + usernameEditText2 = (EditText) findViewById(R.id.username); + passwordEditText2 = (EditText) findViewById(R.id.password); + progressBar = (ProgressBar) findViewById(R.id.loading); + + loginViewModel.getLoginFormState().observe(this, new Observer() { + @Override + public void onChanged(@Nullable LoginFormState loginFormState) { + if (loginFormState == null) { + return; + } + loginButton.setEnabled(loginFormState.isDataValid()); + if (loginFormState.getUsernameError() != null) { + usernameEditText.setError(getString(loginFormState.getUsernameError())); + } + if (loginFormState.getPasswordError() != null) { + passwordEditText.setError(getString(loginFormState.getPasswordError())); + } + } + }); + + loginViewModel.getLoginResult().observe(this, new Observer() { + @Override + public void onChanged(@Nullable LoginResult loginResult) { + if (loginResult == null) { + return; + } + progressBar.setVisibility(View.GONE); + if (loginResult.getError() != null) { + showLoginFailed(loginResult.getError()); + } + if (loginResult.getSuccess() != null) { + updateUiWithUser(loginResult.getSuccess()); + } + setResult(Activity.RESULT_OK); + + //Complete and destroy login activity once successful + finish(); + } + }); + + TextWatcher afterTextChangedListener = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // ignore + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + // ignore + } + + @Override + public void afterTextChanged(Editable s) { + loginViewModel.loginDataChanged(usernameEditText.getText().toString(), + passwordEditText.getText().toString()); + } + }; + usernameEditText.addTextChangedListener(afterTextChangedListener); + passwordEditText.addTextChangedListener(afterTextChangedListener); + passwordEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + loginViewModel.login(usernameEditText.getText().toString(), + passwordEditText.getText().toString()); + } + return false; + } + }); + +// loginButton.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// progressBar.setVisibility(View.VISIBLE); +// loginViewModel.login(usernameEditText.getText().toString(), +// passwordEditText.getText().toString()); +// } +// }); + + login_button = (Button) findViewById(R.id.login); + login_button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + progressBar.setVisibility(View.VISIBLE); + LoginUser(); + } + }); + + register = (TextView) findViewById(R.id.register); + register.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View v){ + openRegisterUserActivity(); + } + }); + + + } + + public void LoginUser(){ + String email = usernameEditText2.getText().toString().trim(); + String password = passwordEditText2.getText().toString().trim(); + mAuth.signInWithEmailAndPassword(email, password).addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(AuthResult authResult) { + Toast.makeText(getApplicationContext(), "Użytkownik zalogowany", Toast.LENGTH_LONG).show(); + progressBar.setVisibility(View.GONE); + openMainActivity(); + + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Toast.makeText(getApplicationContext(), "Logowanie nie powiodła się. Spróbuj ponownie", Toast.LENGTH_LONG).show(); + progressBar.setVisibility(View.GONE); + } + }); + } + + public void openMainActivity(){ + Intent intent = new Intent(this, MainActivity2.class); + startActivity(intent); + } + + public void openRegisterUserActivity(){ + Intent intent = new Intent(this, RegisterUser.class); + startActivity(intent); + } + + private void updateUiWithUser(LoggedInUserView model) { + String welcome = getString(R.string.welcome) + model.getDisplayName(); + // TODO : initiate successful logged in experience + Toast.makeText(getApplicationContext(), welcome, Toast.LENGTH_LONG).show(); + } + + private void showLoginFailed(@StringRes Integer errorString) { + Toast.makeText(getApplicationContext(), errorString, Toast.LENGTH_SHORT).show(); + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginFormState.java b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginFormState.java new file mode 100644 index 0000000..7ed9447 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginFormState.java @@ -0,0 +1,40 @@ +package com.example.wrsd.ui.login; + +import androidx.annotation.Nullable; + +/** + * Data validation state of the login form. + */ +class LoginFormState { + @Nullable + private Integer usernameError; + @Nullable + private Integer passwordError; + private boolean isDataValid; + + LoginFormState(@Nullable Integer usernameError, @Nullable Integer passwordError) { + this.usernameError = usernameError; + this.passwordError = passwordError; + this.isDataValid = false; + } + + LoginFormState(boolean isDataValid) { + this.usernameError = null; + this.passwordError = null; + this.isDataValid = isDataValid; + } + + @Nullable + Integer getUsernameError() { + return usernameError; + } + + @Nullable + Integer getPasswordError() { + return passwordError; + } + + boolean isDataValid() { + return isDataValid; + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginResult.java b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginResult.java new file mode 100644 index 0000000..0cb00f6 --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginResult.java @@ -0,0 +1,31 @@ +package com.example.wrsd.ui.login; + +import androidx.annotation.Nullable; + +/** + * Authentication result : success (user details) or error message. + */ +class LoginResult { + @Nullable + private LoggedInUserView success; + @Nullable + private Integer error; + + LoginResult(@Nullable Integer error) { + this.error = error; + } + + LoginResult(@Nullable LoggedInUserView success) { + this.success = success; + } + + @Nullable + LoggedInUserView getSuccess() { + return success; + } + + @Nullable + Integer getError() { + return error; + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginViewModel.java b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginViewModel.java new file mode 100644 index 0000000..9a28b7a --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginViewModel.java @@ -0,0 +1,70 @@ +package com.example.wrsd.ui.login; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +import android.util.Patterns; + +import com.example.wrsd.data.LoginRepository; +import com.example.wrsd.data.Result; +import com.example.wrsd.data.model.LoggedInUser; +import com.example.wrsd.R; + +public class LoginViewModel extends ViewModel { + + private MutableLiveData loginFormState = new MutableLiveData<>(); + private MutableLiveData loginResult = new MutableLiveData<>(); + private LoginRepository loginRepository; + + LoginViewModel(LoginRepository loginRepository) { + this.loginRepository = loginRepository; + } + + LiveData getLoginFormState() { + return loginFormState; + } + + LiveData getLoginResult() { + return loginResult; + } + + public void login(String username, String password) { + // can be launched in a separate asynchronous job + Result result = loginRepository.login(username, password); + + if (result instanceof Result.Success) { + LoggedInUser data = ((Result.Success) result).getData(); + loginResult.setValue(new LoginResult(new LoggedInUserView(data.getDisplayName()))); + } else { + loginResult.setValue(new LoginResult(R.string.login_failed)); + } + } + + public void loginDataChanged(String username, String password) { + if (!isUserNameValid(username)) { + loginFormState.setValue(new LoginFormState(R.string.invalid_username, null)); + } else if (!isPasswordValid(password)) { + loginFormState.setValue(new LoginFormState(null, R.string.invalid_password)); + } else { + loginFormState.setValue(new LoginFormState(true)); + } + } + + // A placeholder username validation check + private boolean isUserNameValid(String username) { + if (username == null) { + return false; + } + if (username.contains("@")) { + return Patterns.EMAIL_ADDRESS.matcher(username).matches(); + } else { + return !username.trim().isEmpty(); + } + } + + // A placeholder password validation check + private boolean isPasswordValid(String password) { + return password != null && password.trim().length() > 5; + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginViewModelFactory.java b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginViewModelFactory.java new file mode 100644 index 0000000..6e645ac --- /dev/null +++ b/WRSD2/app/src/main/java/com/example/wrsd/ui/login/LoginViewModelFactory.java @@ -0,0 +1,26 @@ +package com.example.wrsd.ui.login; + +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import androidx.annotation.NonNull; + +import com.example.wrsd.data.LoginDataSource; +import com.example.wrsd.data.LoginRepository; + +/** + * ViewModel provider factory to instantiate LoginViewModel. + * Required given LoginViewModel has a non-empty constructor + */ +public class LoginViewModelFactory implements ViewModelProvider.Factory { + + @NonNull + @Override + @SuppressWarnings("unchecked") + public T create(@NonNull Class modelClass) { + if (modelClass.isAssignableFrom(LoginViewModel.class)) { + return (T) new LoginViewModel(LoginRepository.getInstance(new LoginDataSource())); + } else { + throw new IllegalArgumentException("Unknown ViewModel class"); + } + } +} \ No newline at end of file diff --git a/WRSD2/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/WRSD2/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/WRSD2/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/WRSD2/app/src/main/res/drawable/back.png b/WRSD2/app/src/main/res/drawable/back.png new file mode 100644 index 0000000..fc59d95 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/back.png differ diff --git a/WRSD2/app/src/main/res/drawable/bathroom.png b/WRSD2/app/src/main/res/drawable/bathroom.png new file mode 100644 index 0000000..07df60f Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/bathroom.png differ diff --git a/WRSD2/app/src/main/res/drawable/bedroom.png b/WRSD2/app/src/main/res/drawable/bedroom.png new file mode 100644 index 0000000..0c18c20 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/bedroom.png differ diff --git a/WRSD2/app/src/main/res/drawable/glosnik.png b/WRSD2/app/src/main/res/drawable/glosnik.png new file mode 100644 index 0000000..08b4960 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/glosnik.png differ diff --git a/WRSD2/app/src/main/res/drawable/ic_launcher_background.xml b/WRSD2/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/WRSD2/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WRSD2/app/src/main/res/drawable/kibelek.png b/WRSD2/app/src/main/res/drawable/kibelek.png new file mode 100644 index 0000000..fa7170e Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/kibelek.png differ diff --git a/WRSD2/app/src/main/res/drawable/kitchen.png b/WRSD2/app/src/main/res/drawable/kitchen.png new file mode 100644 index 0000000..c66e416 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/kitchen.png differ diff --git a/WRSD2/app/src/main/res/drawable/led.png b/WRSD2/app/src/main/res/drawable/led.png new file mode 100644 index 0000000..b0f4b07 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/led.png differ diff --git a/WRSD2/app/src/main/res/drawable/light.jpg b/WRSD2/app/src/main/res/drawable/light.jpg new file mode 100644 index 0000000..564d55a Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/light.jpg differ diff --git a/WRSD2/app/src/main/res/drawable/livingroom.png b/WRSD2/app/src/main/res/drawable/livingroom.png new file mode 100644 index 0000000..c035fd0 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/livingroom.png differ diff --git a/WRSD2/app/src/main/res/drawable/rolety.png b/WRSD2/app/src/main/res/drawable/rolety.png new file mode 100644 index 0000000..7b769d5 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/rolety.png differ diff --git a/WRSD2/app/src/main/res/drawable/salon.png b/WRSD2/app/src/main/res/drawable/salon.png new file mode 100644 index 0000000..3b0bad4 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/salon.png differ diff --git a/WRSD2/app/src/main/res/drawable/tv.png b/WRSD2/app/src/main/res/drawable/tv.png new file mode 100644 index 0000000..146ae1f Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/tv.png differ diff --git a/WRSD2/app/src/main/res/drawable/wrsdlogo.png b/WRSD2/app/src/main/res/drawable/wrsdlogo.png new file mode 100644 index 0000000..11ae0e4 Binary files /dev/null and b/WRSD2/app/src/main/res/drawable/wrsdlogo.png differ diff --git a/WRSD2/app/src/main/res/layout-w1240dp/activity_login.xml b/WRSD2/app/src/main/res/layout-w1240dp/activity_login.xml new file mode 100644 index 0000000..2445403 --- /dev/null +++ b/WRSD2/app/src/main/res/layout-w1240dp/activity_login.xml @@ -0,0 +1,69 @@ + + + + + + + +