├── app ├── .gitignore ├── src │ ├── main │ │ ├── assets │ │ │ ├── api_info.png │ │ │ ├── api_login.png │ │ │ ├── api_cuenta.png │ │ │ ├── pantalla_01.png │ │ │ ├── estructura_app.png │ │ │ └── respuesta_json.png │ │ ├── res │ │ │ ├── font │ │ │ │ └── playball_regular.ttf │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── color │ │ │ │ └── bottom_nav_selector.xml │ │ │ ├── drawable │ │ │ │ ├── bottom_nav_selector.xml │ │ │ │ ├── baseline_home_24.xml │ │ │ │ ├── ic_back.xml │ │ │ │ ├── baseline_info_24.xml │ │ │ │ ├── api_24px.xml │ │ │ │ ├── menu_redondeado.xml │ │ │ │ ├── ic_launcher_foreground.xml │ │ │ │ └── ic_launcher_background.xml │ │ │ ├── values-night │ │ │ │ └── themes.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── menu │ │ │ │ └── bottom_menu.xml │ │ │ ├── xml │ │ │ │ ├── backup_rules.xml │ │ │ │ └── data_extraction_rules.xml │ │ │ ├── navigation │ │ │ │ └── main_graph.xml │ │ │ ├── values │ │ │ │ ├── themes.xml │ │ │ │ ├── strings.xml │ │ │ │ └── colors.xml │ │ │ └── layout │ │ │ │ ├── fragment_home.xml │ │ │ │ ├── fragment_info.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── items_result.xml │ │ │ │ ├── activity_crear_cuenta.xml │ │ │ │ └── activity_login.xml │ │ ├── java │ │ │ └── pe │ │ │ │ └── pcs │ │ │ │ └── apirestunsplash │ │ │ │ ├── data │ │ │ │ ├── common │ │ │ │ │ ├── Constants.kt │ │ │ │ │ └── HeaderInterceptor.kt │ │ │ │ ├── remote │ │ │ │ │ ├── model │ │ │ │ │ │ ├── UrlsModel.kt │ │ │ │ │ │ └── PhotoModel.kt │ │ │ │ │ └── api │ │ │ │ │ │ └── UnsplashApi.kt │ │ │ │ ├── local │ │ │ │ │ ├── entity │ │ │ │ │ │ ├── PhotoAndUrls.kt │ │ │ │ │ │ ├── UrlsEntity.kt │ │ │ │ │ │ ├── UserEntity.kt │ │ │ │ │ │ └── PhotoEntity.kt │ │ │ │ │ ├── database │ │ │ │ │ │ └── AppDatabase.kt │ │ │ │ │ └── dao │ │ │ │ │ │ ├── UserDao.kt │ │ │ │ │ │ └── PhotoDao.kt │ │ │ │ └── repository │ │ │ │ │ ├── UserRepositoryImp.kt │ │ │ │ │ └── UnsplashRepositoryImpl.kt │ │ │ │ ├── domain │ │ │ │ ├── repository │ │ │ │ │ ├── UserRepository.kt │ │ │ │ │ └── UnsplashRepository.kt │ │ │ │ ├── model │ │ │ │ │ ├── User.kt │ │ │ │ │ ├── Urls.kt │ │ │ │ │ └── Photo.kt │ │ │ │ └── usecase │ │ │ │ │ ├── CreateUserUseCase.kt │ │ │ │ │ ├── getListUnsplashUseCase.kt │ │ │ │ │ └── LoginUseCase.kt │ │ │ │ ├── presentation │ │ │ │ ├── common │ │ │ │ │ ├── ResponseState.kt │ │ │ │ │ ├── UtilsCommon.kt │ │ │ │ │ ├── UtilsSecurity.kt │ │ │ │ │ ├── UtilsDate.kt │ │ │ │ │ ├── MakeCall.kt │ │ │ │ │ └── UtilsMessage.kt │ │ │ │ └── ui │ │ │ │ │ ├── InfoFragment.kt │ │ │ │ │ ├── CrearCuentaViewModel.kt │ │ │ │ │ ├── LoginViewModel.kt │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ ├── HomeViewModel.kt │ │ │ │ │ ├── PhotoAdapter.kt │ │ │ │ │ ├── HomeFragment.kt │ │ │ │ │ ├── LoginActivity.kt │ │ │ │ │ └── CrearCuentaActivity.kt │ │ │ │ ├── ApiUnsplashApp.kt │ │ │ │ └── di │ │ │ │ └── InjectionModule.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── pe │ │ │ └── pcs │ │ │ └── apirestunsplash │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── pe │ │ └── pcs │ │ └── apirestunsplash │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle.kts ├── .idea ├── .gitignore ├── compiler.xml ├── kotlinc.xml ├── misc.xml └── gradle.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle.kts ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /app/src/main/assets/api_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/assets/api_info.png -------------------------------------------------------------------------------- /app/src/main/assets/api_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/assets/api_login.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/assets/api_cuenta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/assets/api_cuenta.png -------------------------------------------------------------------------------- /app/src/main/assets/pantalla_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/assets/pantalla_01.png -------------------------------------------------------------------------------- /app/src/main/assets/estructura_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/assets/estructura_app.png -------------------------------------------------------------------------------- /app/src/main/assets/respuesta_json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/assets/respuesta_json.png -------------------------------------------------------------------------------- /app/src/main/res/font/playball_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/font/playball_regular.ttf -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programadorescs/ApiRestUnsplash/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/common/Constants.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.common 2 | 3 | object Constants { 4 | const val URL_BASE = "https://api.unsplash.com/" 5 | const val API_KEY = "AQUI_DEBES_INGRESAR_TU_API_KEY" 6 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 05 00:08:10 PET 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /app/src/main/res/color/bottom_nav_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bottom_nav_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/remote/model/UrlsModel.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.remote.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class UrlsModel( 6 | @SerializedName("regular") val regular: String="", 7 | @SerializedName("small") val small: String="" 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/repository/UserRepository.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.repository 2 | 3 | import pe.pcs.apirestunsplash.domain.model.User 4 | 5 | interface UserRepository { 6 | suspend fun login(username: String, password: String): User? 7 | 8 | suspend fun create(user: User): Long 9 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/repository/UnsplashRepository.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.repository 2 | 3 | import pe.pcs.apirestunsplash.domain.model.Photo 4 | 5 | interface UnsplashRepository { 6 | 7 | suspend fun getList(): List 8 | 9 | suspend fun getUrlList(): List 10 | 11 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/remote/api/UnsplashApi.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.remote.api 2 | 3 | import pe.pcs.apirestunsplash.data.remote.model.PhotoModel 4 | import retrofit2.http.GET 5 | 6 | interface UnsplashApi { 7 | 8 | @GET("photos/?") 9 | suspend fun getPhotos(): List 10 | 11 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/presentation/common/ResponseState.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.presentation.common 2 | 3 | sealed class ResponseState { 4 | class Loading : ResponseState() 5 | class Success(val data: T) : ResponseState() 6 | class Error(val message: String) : ResponseState() 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_home_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_back.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/local/entity/PhotoAndUrls.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.local.entity 2 | 3 | import androidx.room.Embedded 4 | import androidx.room.Relation 5 | 6 | data class PhotoAndUrls( 7 | @Embedded val photo: PhotoEntity, 8 | @Relation( 9 | parentColumn = "id", 10 | entityColumn = "idphoto" 11 | ) 12 | val urls: UrlsEntity 13 | ) 14 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | 16 | rootProject.name = "ApiRestUnsplash" 17 | include(":app") 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_info_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/menu/bottom_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/pe/pcs/apirestunsplash/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/model/User.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.model 2 | 3 | import pe.pcs.apirestunsplash.data.local.entity.UserEntity 4 | 5 | data class User( 6 | var id: Int = 0, 7 | var name: String = "", 8 | var nickname: String = "", 9 | var password: String = "" 10 | ) 11 | 12 | fun UserEntity.toDomain() = User( 13 | id = id, 14 | name = name, 15 | nickname = nickname, 16 | password = password 17 | ) -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/usecase/CreateUserUseCase.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.usecase 2 | 3 | import pe.pcs.apirestunsplash.domain.model.User 4 | import pe.pcs.apirestunsplash.domain.repository.UserRepository 5 | import javax.inject.Inject 6 | 7 | class CreateUserUseCase @Inject constructor( 8 | private val repository: UserRepository 9 | ) { 10 | suspend operator fun invoke(user: User): Int { 11 | return repository.create(user).toInt() 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/usecase/getListUnsplashUseCase.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.usecase 2 | 3 | import pe.pcs.apirestunsplash.domain.model.Photo 4 | import pe.pcs.apirestunsplash.domain.repository.UnsplashRepository 5 | import javax.inject.Inject 6 | 7 | class getListUnsplashUseCase @Inject constructor( 8 | private val repository: UnsplashRepository 9 | ) { 10 | 11 | suspend operator fun invoke(): List { 12 | return repository.getList() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/usecase/LoginUseCase.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.usecase 2 | 3 | import pe.pcs.apirestunsplash.domain.model.User 4 | import pe.pcs.apirestunsplash.domain.repository.UserRepository 5 | import javax.inject.Inject 6 | 7 | class LoginUseCase @Inject constructor( 8 | private val repository: UserRepository 9 | ) { 10 | suspend operator fun invoke(nickname: String, password: String): User? { 11 | return repository.login(nickname, password) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/model/Urls.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.model 2 | 3 | import pe.pcs.apirestunsplash.data.local.entity.UrlsEntity 4 | import pe.pcs.apirestunsplash.data.remote.model.UrlsModel 5 | 6 | data class Urls( 7 | val regular: String = "", 8 | val small: String = "" 9 | ) 10 | 11 | fun UrlsModel.toDomain() = Urls( 12 | regular = regular, 13 | small = small 14 | ) 15 | 16 | fun UrlsEntity.toDomain() = Urls( 17 | regular = regular, 18 | small = small 19 | ) 20 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/presentation/common/UtilsCommon.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.presentation.common 2 | 3 | import android.content.Context 4 | import android.view.View 5 | import android.view.inputmethod.InputMethodManager 6 | import pe.pcs.apirestunsplash.ApiUnsplashApp 7 | 8 | object UtilsCommon { 9 | fun hideKeyboard(view: View) { 10 | val imm = ApiUnsplashApp.getContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager 11 | imm.hideSoftInputFromWindow(view.windowToken, 0) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/ApiUnsplashApp.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import dagger.hilt.android.HiltAndroidApp 6 | 7 | @HiltAndroidApp 8 | class ApiUnsplashApp : Application() { 9 | 10 | companion object { 11 | private var instancia: ApiUnsplashApp? = null 12 | 13 | fun getContext(): Context { 14 | return instancia!!.applicationContext 15 | } 16 | } 17 | 18 | init { 19 | instancia = this 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/remote/model/PhotoModel.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.remote.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class PhotoModel( 6 | @SerializedName("id") var id: String = "", 7 | @SerializedName("created_at") var created_at: String = "", 8 | @SerializedName("updated_at") var updated_at: String = "", 9 | @SerializedName("alt_description") var description: String? = "", 10 | @SerializedName("likes") var likes: Int, 11 | @SerializedName("urls") var urls: UrlsModel? = UrlsModel() 12 | ) 13 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/presentation/common/UtilsSecurity.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.presentation.common 2 | 3 | import android.util.Base64 4 | import java.security.MessageDigest 5 | 6 | object UtilsSecurity { 7 | fun createSHAHash512(cadena: String): String { 8 | return try { 9 | val digest = MessageDigest.getInstance("SHA-512") 10 | val hash = digest.digest(cadena.toByteArray(charset("UTF-8"))) 11 | Base64.encodeToString(hash, 0).replace("[\n\r]".toRegex(), "") 12 | } catch (ex: Exception) { 13 | throw RuntimeException(ex) 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/api_24px.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/presentation/common/UtilsDate.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.presentation.common 2 | 3 | import java.text.SimpleDateFormat 4 | import java.util.Date 5 | import java.util.Locale 6 | 7 | object UtilsDate { 8 | 9 | fun formatearFecha(fecha: Date): String { 10 | return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(fecha) 11 | } 12 | 13 | fun formatearFecha(fecha: String): String { 14 | val date = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT).parse(fecha) 15 | return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(date!!) 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/local/entity/UrlsEntity.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.local.entity 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import pe.pcs.apirestunsplash.data.remote.model.UrlsModel 7 | 8 | @Entity( 9 | tableName = "urls" 10 | ) 11 | data class UrlsEntity( 12 | @PrimaryKey(autoGenerate = true) 13 | @ColumnInfo(name = "id") var id: Int = 0, 14 | @ColumnInfo("idphoto") var idPhoto: String = "", 15 | @ColumnInfo("regular") val regular: String = "", 16 | @ColumnInfo("small") val small: String = "" 17 | ) 18 | 19 | fun UrlsModel.toDatabase() = UrlsEntity( 20 | regular = regular, 21 | small = small 22 | ) -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/presentation/ui/InfoFragment.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.presentation.ui 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import pe.pcs.apirestunsplash.databinding.FragmentInfoBinding 9 | 10 | 11 | class InfoFragment : Fragment() { 12 | 13 | private lateinit var binding: FragmentInfoBinding 14 | 15 | override fun onCreateView( 16 | inflater: LayoutInflater, container: ViewGroup?, 17 | savedInstanceState: Bundle? 18 | ): View? { 19 | binding = FragmentInfoBinding.inflate(layoutInflater) 20 | return binding.root 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/navigation/main_graph.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/pe/pcs/apirestunsplash/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("pe.pcs.apirestunsplash", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/repository/UserRepositoryImp.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.repository 2 | 3 | import pe.pcs.apirestunsplash.data.local.dao.UserDao 4 | import pe.pcs.apirestunsplash.data.local.entity.toDatabase 5 | import pe.pcs.apirestunsplash.domain.model.User 6 | import pe.pcs.apirestunsplash.domain.model.toDomain 7 | import pe.pcs.apirestunsplash.domain.repository.UserRepository 8 | import javax.inject.Inject 9 | 10 | class UserRepositoryImp @Inject constructor( 11 | private val dao: UserDao 12 | ): UserRepository { 13 | override suspend fun login(username: String, password: String): User? { 14 | return dao.login(username, password)?.toDomain() 15 | } 16 | 17 | override suspend fun create(user: User): Long { 18 | return dao.createTransaction(user.toDatabase()) 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/local/entity/UserEntity.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.local.entity 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.Index 6 | import androidx.room.PrimaryKey 7 | import pe.pcs.apirestunsplash.domain.model.User 8 | 9 | @Entity( 10 | tableName = "user", 11 | indices = [Index(value = ["nickname"], unique = true)] 12 | ) 13 | data class UserEntity( 14 | @PrimaryKey(autoGenerate = true) 15 | @ColumnInfo("id") var id: Int = 0, 16 | @ColumnInfo("name") var name: String = "", 17 | @ColumnInfo("nickname") var nickname: String = "", 18 | @ColumnInfo("password") var password: String = "" 19 | ) 20 | 21 | fun User.toDatabase() = UserEntity( 22 | id = id, 23 | name = name, 24 | nickname = nickname, 25 | password = password 26 | ) -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/local/database/AppDatabase.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.local.database 2 | 3 | import androidx.room.Database 4 | import androidx.room.RoomDatabase 5 | import pe.pcs.apirestunsplash.data.local.dao.PhotoDao 6 | import pe.pcs.apirestunsplash.data.local.dao.UserDao 7 | import pe.pcs.apirestunsplash.data.local.entity.PhotoEntity 8 | import pe.pcs.apirestunsplash.data.local.entity.UrlsEntity 9 | import pe.pcs.apirestunsplash.data.local.entity.UserEntity 10 | 11 | 12 | @Database( 13 | entities = [ 14 | PhotoEntity::class, 15 | UrlsEntity::class, 16 | UserEntity::class 17 | ], 18 | version = 1, 19 | exportSchema = false 20 | ) 21 | abstract class AppDatabase: RoomDatabase() { 22 | 23 | abstract fun photoDao(): PhotoDao 24 | 25 | abstract fun userDao(): UserDao 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/data/local/entity/PhotoEntity.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.data.local.entity 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import pe.pcs.apirestunsplash.data.remote.model.PhotoModel 7 | 8 | @Entity( 9 | tableName = "photo" 10 | ) 11 | data class PhotoEntity( 12 | @PrimaryKey 13 | @ColumnInfo("id") var id: String = "", 14 | @ColumnInfo("createdAt") var createdAt: String = "", 15 | @ColumnInfo("updatedAt") var updatedAt: String = "", 16 | @ColumnInfo("description") var description: String? = "", 17 | @ColumnInfo("likes") val likes: Int = 0 18 | ) 19 | 20 | fun PhotoModel.toDatabase() = PhotoEntity( 21 | id = id, 22 | createdAt = created_at, 23 | updatedAt = updated_at, 24 | description = description, 25 | likes = likes 26 | ) -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/domain/model/Photo.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.domain.model 2 | 3 | import pe.pcs.apirestunsplash.data.local.entity.PhotoEntity 4 | import pe.pcs.apirestunsplash.data.remote.model.PhotoModel 5 | 6 | data class Photo( 7 | val id: String = "", 8 | val createdAt: String = "", 9 | val updatedAt: String = "", 10 | val description: String? = "", 11 | val likes: Int, 12 | var urls: Urls? = Urls() 13 | ) 14 | 15 | fun PhotoModel.toDomain() = Photo( 16 | id = id, 17 | createdAt = created_at, 18 | updatedAt = updated_at, 19 | description = description, 20 | likes = likes, 21 | urls = urls?.toDomain() 22 | ) 23 | 24 | fun PhotoEntity.toDomain() = Photo( 25 | id = id, 26 | createdAt = createdAt, 27 | updatedAt = updatedAt, 28 | description = description, 29 | likes = likes 30 | ) -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/presentation/common/MakeCall.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.presentation.common 2 | 3 | import kotlinx.coroutines.Dispatchers 4 | import kotlinx.coroutines.withContext 5 | import retrofit2.HttpException 6 | import java.net.UnknownHostException 7 | 8 | suspend fun makeCall( 9 | call: suspend () -> T 10 | ): ResponseState { 11 | return withContext(Dispatchers.IO) { 12 | try { 13 | ResponseState.Success(call()) 14 | } catch (e: UnknownHostException) { 15 | // UnknownHostException -> Error de internet o red 16 | ResponseState.Error(e.message.toString()) 17 | } catch (e: HttpException) { 18 | ResponseState.Error(e.message.toString()) 19 | } catch (e: Exception) { 20 | ResponseState.Error(e.message.toString()) 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/java/pe/pcs/apirestunsplash/presentation/common/UtilsMessage.kt: -------------------------------------------------------------------------------- 1 | package pe.pcs.apirestunsplash.presentation.common 2 | 3 | import android.content.Context 4 | import android.widget.Toast 5 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 6 | import pe.pcs.apirestunsplash.ApiUnsplashApp 7 | 8 | object UtilsMessage { 9 | 10 | fun showAlertOk(titulo: String?, mensaje: String?, contexto: Context) { 11 | val builder = MaterialAlertDialogBuilder(contexto) 12 | builder.setMessage(mensaje) 13 | .setTitle(titulo) 14 | .setCancelable(false) 15 | .setPositiveButton("Aceptar") { dialog, _ -> dialog.cancel() } 16 | builder.create().show() 17 | } 18 | 19 | fun showToast(mensaje: String) { 20 | Toast.makeText( 21 | ApiUnsplashApp.getContext(), 22 | mensaje, 23 | Toast.LENGTH_LONG 24 | ).show() 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 20 |