From 9f03838fba2f103eca9a5bd28e89e206103a8184 Mon Sep 17 00:00:00 2001 From: biloute02 Date: Thu, 14 Dec 2023 22:32:55 +0100 Subject: [PATCH] Deux nouveaux fragments. --- .gitignore | 12 +- .idea/.gitignore | 3 - .idea/.name | 1 - .idea/compiler.xml | 6 - .idea/gradle.xml | 20 --- .idea/kotlinc.xml | 6 - .idea/misc.xml | 7 - .idea/vcs.xml | 6 - app/build.gradle.kts | 8 ++ .../java/com/example/palto/ItemFragment.kt | 61 ++++++++ .../palto/MyItemRecyclerViewAdapter.kt | 49 +++++++ .../java/com/example/palto/PaltoActivity.kt | 11 +- .../com/example/palto/data/LoginDataSource.kt | 24 ++++ .../com/example/palto/data/LoginRepository.kt | 46 ++++++ .../java/com/example/palto/data/Result.kt | 18 +++ .../example/palto/data/model/LoggedInUser.kt | 9 ++ .../palto/placeholder/PlaceholderContent.kt | 57 ++++++++ .../palto/ui/login/LoggedInUserView.kt | 9 ++ .../example/palto/ui/login/LoginFormState.kt | 10 ++ .../example/palto/ui/login/LoginFragment.kt | 131 ++++++++++++++++++ .../com/example/palto/ui/login/LoginResult.kt | 9 ++ .../example/palto/ui/login/LoginViewModel.kt | 55 ++++++++ .../palto/ui/login/LoginViewModelFactory.kt | 25 ++++ app/src/main/res/layout/activity_login.xml | 19 --- app/src/main/res/layout/activity_palto.xml | 13 ++ app/src/main/res/layout/fragment_item.xml | 20 +++ .../main/res/layout/fragment_item_list.xml | 13 ++ app/src/main/res/layout/fragment_login.xml | 78 +++++++++++ app/src/main/res/navigation/nav_graph.xml | 22 ++- app/src/main/res/values/dimens.xml | 6 + app/src/main/res/values/strings.xml | 9 ++ 31 files changed, 684 insertions(+), 79 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/.name delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/kotlinc.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml create mode 100644 app/src/main/java/com/example/palto/ItemFragment.kt create mode 100644 app/src/main/java/com/example/palto/MyItemRecyclerViewAdapter.kt create mode 100644 app/src/main/java/com/example/palto/data/LoginDataSource.kt create mode 100644 app/src/main/java/com/example/palto/data/LoginRepository.kt create mode 100644 app/src/main/java/com/example/palto/data/Result.kt create mode 100644 app/src/main/java/com/example/palto/data/model/LoggedInUser.kt create mode 100644 app/src/main/java/com/example/palto/placeholder/PlaceholderContent.kt create mode 100644 app/src/main/java/com/example/palto/ui/login/LoggedInUserView.kt create mode 100644 app/src/main/java/com/example/palto/ui/login/LoginFormState.kt create mode 100644 app/src/main/java/com/example/palto/ui/login/LoginFragment.kt create mode 100644 app/src/main/java/com/example/palto/ui/login/LoginResult.kt create mode 100644 app/src/main/java/com/example/palto/ui/login/LoginViewModel.kt create mode 100644 app/src/main/java/com/example/palto/ui/login/LoginViewModelFactory.kt delete mode 100644 app/src/main/res/layout/activity_login.xml create mode 100644 app/src/main/res/layout/fragment_item.xml create mode 100644 app/src/main/res/layout/fragment_item_list.xml create mode 100644 app/src/main/res/layout/fragment_login.xml create mode 100644 app/src/main/res/values/dimens.xml diff --git a/.gitignore b/.gitignore index aa724b7..ae8485f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,9 @@ *.iml .gradle -/local.properties -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml +local.properties +.idea .DS_Store -/build -/captures +build .externalNativeBuild .cxx local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 7768bde..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -Palto \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index b589d56..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 61d81f6..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml deleted file mode 100644 index fdf8d99..0000000 --- a/.idea/kotlinc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index b0137f1..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0ebe5a4..39d63cb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -30,6 +30,9 @@ android { jvmTarget = "1.8" } buildToolsVersion = "33.0.1" + buildFeatures { + viewBinding = true + } } dependencies { @@ -39,6 +42,11 @@ dependencies { implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("androidx.navigation:navigation-fragment-ktx:2.7.5") implementation("androidx.navigation:navigation-ui-ktx:2.7.5") + implementation("androidx.annotation:annotation:1.7.0") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") + implementation("androidx.legacy:legacy-support-v4:1.0.0") + implementation("androidx.recyclerview:recyclerview:1.3.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") diff --git a/app/src/main/java/com/example/palto/ItemFragment.kt b/app/src/main/java/com/example/palto/ItemFragment.kt new file mode 100644 index 0000000..c4c3d0c --- /dev/null +++ b/app/src/main/java/com/example/palto/ItemFragment.kt @@ -0,0 +1,61 @@ +package com.example.palto + +import android.os.Bundle +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.example.palto.placeholder.PlaceholderContent + +/** + * A fragment representing a list of Items. + */ +class ItemFragment : Fragment() { + + private var columnCount = 1 + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + arguments?.let { + columnCount = it.getInt(ARG_COLUMN_COUNT) + } + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.fragment_item_list, container, false) + + // Set the adapter + if (view is RecyclerView) { + with(view) { + layoutManager = when { + columnCount <= 1 -> LinearLayoutManager(context) + else -> GridLayoutManager(context, columnCount) + } + adapter = MyItemRecyclerViewAdapter(PlaceholderContent.ITEMS) + } + } + return view + } + + companion object { + + // TODO: Customize parameter argument names + const val ARG_COLUMN_COUNT = "column-count" + + // TODO: Customize parameter initialization + @JvmStatic + fun newInstance(columnCount: Int) = + ItemFragment().apply { + arguments = Bundle().apply { + putInt(ARG_COLUMN_COUNT, columnCount) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/MyItemRecyclerViewAdapter.kt b/app/src/main/java/com/example/palto/MyItemRecyclerViewAdapter.kt new file mode 100644 index 0000000..4b8bd0d --- /dev/null +++ b/app/src/main/java/com/example/palto/MyItemRecyclerViewAdapter.kt @@ -0,0 +1,49 @@ +package com.example.palto + +import androidx.recyclerview.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView + +import com.example.palto.placeholder.PlaceholderContent.PlaceholderItem +import com.example.palto.databinding.FragmentItemBinding + +/** + * [RecyclerView.Adapter] that can display a [PlaceholderItem]. + * TODO: Replace the implementation with code for your data type. + */ +class MyItemRecyclerViewAdapter( + private val values: List +) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + + return ViewHolder( + FragmentItemBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val item = values[position] + holder.idView.text = item.id + holder.contentView.text = item.content + } + + override fun getItemCount(): Int = values.size + + inner class ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) { + val idView: TextView = binding.itemNumber + val contentView: TextView = binding.content + + override fun toString(): String { + return super.toString() + " '" + contentView.text + "'" + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/PaltoActivity.kt b/app/src/main/java/com/example/palto/PaltoActivity.kt index af7d27c..bbfb52c 100644 --- a/app/src/main/java/com/example/palto/PaltoActivity.kt +++ b/app/src/main/java/com/example/palto/PaltoActivity.kt @@ -1,18 +1,21 @@ package com.example.palto +import android.app.Activity import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity +import java.net.URL + class PaltoActivity : AppCompatActivity() { private var nfcAdapter: NfcAdapter? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_login) + setContentView(R.layout.activity_palto) // get the NFC Adapter this.nfcAdapter = NfcAdapter.getDefaultAdapter(this) @@ -27,6 +30,12 @@ class PaltoActivity : AppCompatActivity() { if (!(this.nfcAdapter!!.isEnabled)) { Log.w("NFC", "NFC is not enabled") } + + // TEST + /* + val url = URL("https://www.faraphel.fr/palto/api/auth/token/") + val connection = url.openConnection() + val auth_data = Json.decodeFromString(connection.content)*/ } override fun onResume() { diff --git a/app/src/main/java/com/example/palto/data/LoginDataSource.kt b/app/src/main/java/com/example/palto/data/LoginDataSource.kt new file mode 100644 index 0000000..450e4c0 --- /dev/null +++ b/app/src/main/java/com/example/palto/data/LoginDataSource.kt @@ -0,0 +1,24 @@ +package com.example.palto.data + +import com.example.palto.data.model.LoggedInUser +import java.io.IOException + +/** + * Class that handles authentication w/ login credentials and retrieves user information. + */ +class LoginDataSource { + + fun login(username: String, password: String): Result { + try { + // TODO: handle loggedInUser authentication + val fakeUser = LoggedInUser(java.util.UUID.randomUUID().toString(), "Jane Doe") + return Result.Success(fakeUser) + } catch (e: Throwable) { + return Result.Error(IOException("Error logging in", e)) + } + } + + fun logout() { + // TODO: revoke authentication + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/data/LoginRepository.kt b/app/src/main/java/com/example/palto/data/LoginRepository.kt new file mode 100644 index 0000000..2c819bf --- /dev/null +++ b/app/src/main/java/com/example/palto/data/LoginRepository.kt @@ -0,0 +1,46 @@ +package com.example.palto.data + +import com.example.palto.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. + */ + +class LoginRepository(val dataSource: LoginDataSource) { + + // in-memory cache of the loggedInUser object + var user: LoggedInUser? = null + private set + + val isLoggedIn: Boolean + get() = user != null + + init { + // If user credentials will be cached in local storage, it is recommended it be encrypted + // @see https://developer.android.com/training/articles/keystore + user = null + } + + fun logout() { + user = null + dataSource.logout() + } + + fun login(username: String, password: String): Result { + // handle login + val result = dataSource.login(username, password) + + if (result is Result.Success) { + setLoggedInUser(result.data) + } + + return result + } + + private fun setLoggedInUser(loggedInUser: LoggedInUser) { + this.user = loggedInUser + // If user credentials will be cached in local storage, it is recommended it be encrypted + // @see https://developer.android.com/training/articles/keystore + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/data/Result.kt b/app/src/main/java/com/example/palto/data/Result.kt new file mode 100644 index 0000000..be27f93 --- /dev/null +++ b/app/src/main/java/com/example/palto/data/Result.kt @@ -0,0 +1,18 @@ +package com.example.palto.data + +/** + * A generic class that holds a value with its loading status. + * @param + */ +sealed class Result { + + data class Success(val data: T) : Result() + data class Error(val exception: Exception) : Result() + + override fun toString(): String { + return when (this) { + is Success<*> -> "Success[data=$data]" + is Error -> "Error[exception=$exception]" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/data/model/LoggedInUser.kt b/app/src/main/java/com/example/palto/data/model/LoggedInUser.kt new file mode 100644 index 0000000..b9e4156 --- /dev/null +++ b/app/src/main/java/com/example/palto/data/model/LoggedInUser.kt @@ -0,0 +1,9 @@ +package com.example.palto.data.model + +/** + * Data class that captures user information for logged in users retrieved from LoginRepository + */ +data class LoggedInUser( + val userId: String, + val displayName: String +) \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/placeholder/PlaceholderContent.kt b/app/src/main/java/com/example/palto/placeholder/PlaceholderContent.kt new file mode 100644 index 0000000..553c509 --- /dev/null +++ b/app/src/main/java/com/example/palto/placeholder/PlaceholderContent.kt @@ -0,0 +1,57 @@ +package com.example.palto.placeholder + +import java.util.ArrayList +import java.util.HashMap + +/** + * Helper class for providing sample content for user interfaces created by + * Android template wizards. + * + * TODO: Replace all uses of this class before publishing your app. + */ +object PlaceholderContent { + + /** + * An array of sample (placeholder) items. + */ + val ITEMS: MutableList = ArrayList() + + /** + * A map of sample (placeholder) items, by ID. + */ + val ITEM_MAP: MutableMap = HashMap() + + private val COUNT = 25 + + init { + // Add some sample items. + for (i in 1..COUNT) { + addItem(createPlaceholderItem(i)) + } + } + + private fun addItem(item: PlaceholderItem) { + ITEMS.add(item) + ITEM_MAP.put(item.id, item) + } + + private fun createPlaceholderItem(position: Int): PlaceholderItem { + return PlaceholderItem(position.toString(), "Item " + position, makeDetails(position)) + } + + private fun makeDetails(position: Int): String { + val builder = StringBuilder() + builder.append("Details about Item: ").append(position) + for (i in 0..position - 1) { + builder.append("\nMore details information here.") + } + return builder.toString() + } + + /** + * A placeholder item representing a piece of content. + */ + data class PlaceholderItem(val id: String, val content: String, val details: String) { + override fun toString(): String = content + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/login/LoggedInUserView.kt b/app/src/main/java/com/example/palto/ui/login/LoggedInUserView.kt new file mode 100644 index 0000000..e8a0b0c --- /dev/null +++ b/app/src/main/java/com/example/palto/ui/login/LoggedInUserView.kt @@ -0,0 +1,9 @@ +package com.example.palto.ui.login + +/** + * User details post authentication that is exposed to the UI + */ +data class LoggedInUserView( + val displayName: String + //... other data fields that may be accessible to the UI +) \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/login/LoginFormState.kt b/app/src/main/java/com/example/palto/ui/login/LoginFormState.kt new file mode 100644 index 0000000..ffcaeac --- /dev/null +++ b/app/src/main/java/com/example/palto/ui/login/LoginFormState.kt @@ -0,0 +1,10 @@ +package com.example.palto.ui.login + +/** + * Data validation state of the login form. + */ +data class LoginFormState( + val usernameError: Int? = null, + val passwordError: Int? = null, + val isDataValid: Boolean = false +) \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/login/LoginFragment.kt b/app/src/main/java/com/example/palto/ui/login/LoginFragment.kt new file mode 100644 index 0000000..17435f5 --- /dev/null +++ b/app/src/main/java/com/example/palto/ui/login/LoginFragment.kt @@ -0,0 +1,131 @@ +package com.example.palto.ui.login + +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.annotation.StringRes +import androidx.fragment.app.Fragment +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.EditorInfo +import android.widget.Button +import android.widget.EditText +import android.widget.ProgressBar +import android.widget.Toast +import com.example.palto.databinding.FragmentLoginBinding + +import com.example.palto.R + +class LoginFragment : Fragment() { + + private lateinit var loginViewModel: LoginViewModel + private var _binding: FragmentLoginBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + + _binding = FragmentLoginBinding.inflate(inflater, container, false) + return binding.root + + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + loginViewModel = ViewModelProvider(this, LoginViewModelFactory()) + .get(LoginViewModel::class.java) + + val usernameEditText = binding.username + val passwordEditText = binding.password + val loginButton = binding.login + val loadingProgressBar = binding.loading + + loginViewModel.loginFormState.observe(viewLifecycleOwner, + Observer { loginFormState -> + if (loginFormState == null) { + return@Observer + } + loginButton.isEnabled = loginFormState.isDataValid + loginFormState.usernameError?.let { + usernameEditText.error = getString(it) + } + loginFormState.passwordError?.let { + passwordEditText.error = getString(it) + } + }) + + loginViewModel.loginResult.observe(viewLifecycleOwner, + Observer { loginResult -> + loginResult ?: return@Observer + loadingProgressBar.visibility = View.GONE + loginResult.error?.let { + showLoginFailed(it) + } + loginResult.success?.let { + updateUiWithUser(it) + } + }) + + val afterTextChangedListener = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + // ignore + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + // ignore + } + + override fun afterTextChanged(s: Editable) { + loginViewModel.loginDataChanged( + usernameEditText.text.toString(), + passwordEditText.text.toString() + ) + } + } + usernameEditText.addTextChangedListener(afterTextChangedListener) + passwordEditText.addTextChangedListener(afterTextChangedListener) + passwordEditText.setOnEditorActionListener { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + loginViewModel.login( + usernameEditText.text.toString(), + passwordEditText.text.toString() + ) + } + false + } + + loginButton.setOnClickListener { + loadingProgressBar.visibility = View.VISIBLE + loginViewModel.login( + usernameEditText.text.toString(), + passwordEditText.text.toString() + ) + } + } + + private fun updateUiWithUser(model: LoggedInUserView) { + val welcome = getString(R.string.welcome) + model.displayName + // TODO : initiate successful logged in experience + val appContext = context?.applicationContext ?: return + Toast.makeText(appContext, welcome, Toast.LENGTH_LONG).show() + } + + private fun showLoginFailed(@StringRes errorString: Int) { + val appContext = context?.applicationContext ?: return + Toast.makeText(appContext, errorString, Toast.LENGTH_LONG).show() + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/login/LoginResult.kt b/app/src/main/java/com/example/palto/ui/login/LoginResult.kt new file mode 100644 index 0000000..9367f89 --- /dev/null +++ b/app/src/main/java/com/example/palto/ui/login/LoginResult.kt @@ -0,0 +1,9 @@ +package com.example.palto.ui.login + +/** + * Authentication result : success (user details) or error message. + */ +data class LoginResult( + val success: LoggedInUserView? = null, + val error: Int? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/login/LoginViewModel.kt b/app/src/main/java/com/example/palto/ui/login/LoginViewModel.kt new file mode 100644 index 0000000..aef57fa --- /dev/null +++ b/app/src/main/java/com/example/palto/ui/login/LoginViewModel.kt @@ -0,0 +1,55 @@ +package com.example.palto.ui.login + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import android.util.Patterns +import com.example.palto.data.LoginRepository +import com.example.palto.data.Result + +import com.example.palto.R + +class LoginViewModel(private val loginRepository: LoginRepository) : ViewModel() { + + private val _loginForm = MutableLiveData() + val loginFormState: LiveData = _loginForm + + private val _loginResult = MutableLiveData() + val loginResult: LiveData = _loginResult + + fun login(username: String, password: String) { + // can be launched in a separate asynchronous job + val result = loginRepository.login(username, password) + + if (result is Result.Success) { + _loginResult.value = + LoginResult(success = LoggedInUserView(displayName = result.data.displayName)) + } else { + _loginResult.value = LoginResult(error = R.string.login_failed) + } + } + + fun loginDataChanged(username: String, password: String) { + if (!isUserNameValid(username)) { + _loginForm.value = LoginFormState(usernameError = R.string.invalid_username) + } else if (!isPasswordValid(password)) { + _loginForm.value = LoginFormState(passwordError = R.string.invalid_password) + } else { + _loginForm.value = LoginFormState(isDataValid = true) + } + } + + // A placeholder username validation check + private fun isUserNameValid(username: String): Boolean { + return if (username.contains("@")) { + Patterns.EMAIL_ADDRESS.matcher(username).matches() + } else { + username.isNotBlank() + } + } + + // A placeholder password validation check + private fun isPasswordValid(password: String): Boolean { + return password.length > 5 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/login/LoginViewModelFactory.kt b/app/src/main/java/com/example/palto/ui/login/LoginViewModelFactory.kt new file mode 100644 index 0000000..cc18366 --- /dev/null +++ b/app/src/main/java/com/example/palto/ui/login/LoginViewModelFactory.kt @@ -0,0 +1,25 @@ +package com.example.palto.ui.login + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.example.palto.data.LoginDataSource +import com.example.palto.data.LoginRepository + +/** + * ViewModel provider factory to instantiate LoginViewModel. + * Required given LoginViewModel has a non-empty constructor + */ +class LoginViewModelFactory : ViewModelProvider.Factory { + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(LoginViewModel::class.java)) { + return LoginViewModel( + loginRepository = LoginRepository( + dataSource = LoginDataSource() + ) + ) as T + } + throw IllegalArgumentException("Unknown ViewModel class") + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml deleted file mode 100644 index 0792b7e..0000000 --- a/app/src/main/res/layout/activity_login.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_palto.xml b/app/src/main/res/layout/activity_palto.xml index 77d9ef6..3a70781 100644 --- a/app/src/main/res/layout/activity_palto.xml +++ b/app/src/main/res/layout/activity_palto.xml @@ -1,6 +1,19 @@ + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_item.xml b/app/src/main/res/layout/fragment_item.xml new file mode 100644 index 0000000..1877568 --- /dev/null +++ b/app/src/main/res/layout/fragment_item.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_item_list.xml b/app/src/main/res/layout/fragment_item_list.xml new file mode 100644 index 0000000..435cfa1 --- /dev/null +++ b/app/src/main/res/layout/fragment_item_list.xml @@ -0,0 +1,13 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml new file mode 100644 index 0000000..5b9ac0b --- /dev/null +++ b/app/src/main/res/layout/fragment_login.xml @@ -0,0 +1,78 @@ + + + + + + + +