diff --git a/Mobile/GameOfThrones/.gitignore b/Mobile/GameOfThrones/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/Mobile/GameOfThrones/.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/Mobile/GameOfThrones/.idea/.gitignore b/Mobile/GameOfThrones/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/Mobile/GameOfThrones/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/Mobile/GameOfThrones/.idea/.name b/Mobile/GameOfThrones/.idea/.name new file mode 100644 index 0000000..2febe63 --- /dev/null +++ b/Mobile/GameOfThrones/.idea/.name @@ -0,0 +1 @@ +GameOfThrones \ No newline at end of file diff --git a/Mobile/GameOfThrones/.idea/compiler.xml b/Mobile/GameOfThrones/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/Mobile/GameOfThrones/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/.idea/gradle.xml b/Mobile/GameOfThrones/.idea/gradle.xml new file mode 100644 index 0000000..a2d7c21 --- /dev/null +++ b/Mobile/GameOfThrones/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/.idea/misc.xml b/Mobile/GameOfThrones/.idea/misc.xml new file mode 100644 index 0000000..bdd9278 --- /dev/null +++ b/Mobile/GameOfThrones/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/.idea/vcs.xml b/Mobile/GameOfThrones/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/Mobile/GameOfThrones/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/.gitignore b/Mobile/GameOfThrones/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/Mobile/GameOfThrones/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/build.gradle b/Mobile/GameOfThrones/app/build.gradle new file mode 100644 index 0000000..af7313d --- /dev/null +++ b/Mobile/GameOfThrones/app/build.gradle @@ -0,0 +1,100 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' + id 'kotlin-android' + id 'kotlin-kapt' + id 'dagger.hilt.android.plugin' + id 'com.google.dagger.hilt.android' +} + +android { + namespace 'com.example.gameofthrones' + compileSdk 33 + + defaultConfig { + applicationId "com.example.gameofthrones" + minSdk 24 + targetSdk 33 + 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 + } + kotlinOptions { + jvmTarget = '1.8' + } + buildFeatures { + viewBinding true + } +} +kapt { + correctErrorTypes true +} +dependencies { + + implementation 'androidx.core:core-ktx:1.10.1' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.9.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.dagger:hilt-android:2.45' + kapt 'com.google.dagger:hilt-compiler:2.45' + implementation("androidx.hilt:hilt-navigation-fragment:1.0.0") + //Retrofit + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.retrofit2:converter-gson:2.9.0' + + //Lifecycle + def lifecycle_version = "2.5.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation "androidx.fragment:fragment-ktx:1.5.2" + //Kotlin Coroutines + def coroutines_android_version = '1.3.7' + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_android_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_android_version" + + //Dagger - Hilt + implementation "com.google.dagger:hilt-android:2.45" + kapt "com.google.dagger:hilt-android-compiler:2.40.5" + implementation 'com.google.dagger:hilt-android:2.45' + kapt 'com.google.dagger:hilt-compiler:2.45' + implementation "androidx.navigation:navigation-compose:2.5.3" + implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0" + kapt "androidx.hilt:hilt-compiler:1.0.0" + //Room + def room_version = "2.3.0" + implementation "androidx.room:room-runtime:$room_version" + implementation "androidx.room:room-ktx:$room_version" + kapt "androidx.room:room-compiler:$room_version" + + //Navigation + def nav_version = "2.3.0" + implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" + implementation "androidx.navigation:navigation-ui-ktx:$nav_version" + + //Glide + implementation 'com.github.bumptech.glide:glide:4.11.0' + kapt 'com.github.bumptech.glide:compiler:4.11.0' + + //Timber + implementation 'com.jakewharton.timber:timber:4.7.1' + + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/proguard-rules.pro b/Mobile/GameOfThrones/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/Mobile/GameOfThrones/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/Mobile/GameOfThrones/app/src/androidTest/java/com/example/gameofthrones/ExampleInstrumentedTest.kt b/Mobile/GameOfThrones/app/src/androidTest/java/com/example/gameofthrones/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..c55a0b9 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/androidTest/java/com/example/gameofthrones/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.example.gameofthrones + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.gameofthrones", appContext.packageName) + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/AndroidManifest.xml b/Mobile/GameOfThrones/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..270d754 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/GotApplication.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/GotApplication.kt new file mode 100644 index 0000000..6aa513b --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/GotApplication.kt @@ -0,0 +1,15 @@ +package com.example.gameofthrones + +import android.app.Application +import dagger.hilt.android.HiltAndroidApp +import timber.log.Timber + +@HiltAndroidApp +class GotApplication: Application() { + override fun onCreate() { + super.onCreate() + if (BuildConfig.DEBUG) { + Timber.plant(Timber.DebugTree()) + } + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/adapters/GameOfThronesAdapter.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/adapters/GameOfThronesAdapter.kt new file mode 100644 index 0000000..8d0b64a --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/adapters/GameOfThronesAdapter.kt @@ -0,0 +1,29 @@ +package com.example.gameofthrones.adapters + +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import android.view.LayoutInflater +import android.widget.TextView +import com.example.gameofthrones.R +import com.example.gameofthrones.data.GameOfThronesResponsesItem + +class GameOfThronesAdapter(private val houses: List) : RecyclerView.Adapter(){ + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val inflater = LayoutInflater.from(parent.context) + val view = inflater.inflate(R.layout.item_game_of_thrones, parent, false) + return ViewHolder(view) + } + override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(houses[position]) + + override fun getItemCount() = houses.size + + class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + fun bind(item: GameOfThronesResponsesItem) { + val textView: TextView = itemView.findViewById(R.id.tv_name) + textView.text = item.name + } + } + +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/api/GameOfThronesApi.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/api/GameOfThronesApi.kt new file mode 100644 index 0000000..c7c5d0a --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/api/GameOfThronesApi.kt @@ -0,0 +1,12 @@ +package com.example.gameofthrones.api + +import com.example.gameofthrones.data.GameOfThronesResponsesItem +import retrofit2.Call +import retrofit2.http.GET + +interface GameOfThronesApi { + @GET("api/houses") +fun getHouses( ):Call> + + +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/api/RetrofitInstance.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/api/RetrofitInstance.kt new file mode 100644 index 0000000..440e9a4 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/api/RetrofitInstance.kt @@ -0,0 +1,22 @@ +package com.example.gameofthrones.api +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import com.example.gameofthrones.util.Constants.Companion.BASE_URL +import retrofit2.converter.moshi.MoshiConverterFactory + +class RetrofitInstance { + + companion object { + var mRetrofit: Retrofit? = null + + fun getInstance(): Retrofit{ + return Retrofit.Builder().baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + // we need to add converter factory to + // convert JSON object to Java object + .build() + + } +}} diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/GameOfThronesResponsesItem.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/GameOfThronesResponsesItem.kt new file mode 100644 index 0000000..6ec5ab2 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/GameOfThronesResponsesItem.kt @@ -0,0 +1,21 @@ +package com.example.gameofthrones.data + +import com.google.gson.annotations.SerializedName + +data class GameOfThronesResponsesItem( + val url: String, + val name: String, + val region: String, + val coatOfArms: String, + val words: String, + val titles: List, + val seats: List, + val currentLord: String, + val heir: String, + val overlord: String, + val founded: String, + val founder: String, + val diedOut: String, + val ancestralWeapons: List, + val cadetBranches: List, + val swornMembers: List) \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/HouseGameOfThrones.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/HouseGameOfThrones.kt new file mode 100644 index 0000000..5871fd7 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/HouseGameOfThrones.kt @@ -0,0 +1,31 @@ +package com.example.gameofthrones.data.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey +import androidx.room.TypeConverters + +@Entity(tableName = "houses") +data class HouseGameOfThrones( + @TypeConverters(StringListTypeConverter::class) + val ancestralWeapons: List? = null, + val cadetBranches: List? = null, + val coatOfArms: String, + val currentLord: String, + val diedOut: String, + val founded: String, + val founder: String, + val heir: String, + val name: String, + val overlord: String, + val region: String, + val seats: List, + val swornMembers: List? = null, + val titles: List? = null, + val url: String, + val words: String +) +{ + @PrimaryKey(autoGenerate = true) + var id: Int? = null +} + diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/HouseList.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/HouseList.kt new file mode 100644 index 0000000..c4175c3 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/HouseList.kt @@ -0,0 +1,6 @@ +package com.example.gameofthrones.data.entities + +data class HouseList ( + val results: List? = null + +) diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/StringListTypeConverter.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/StringListTypeConverter.kt new file mode 100644 index 0000000..d4b3cbc --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/entities/StringListTypeConverter.kt @@ -0,0 +1,20 @@ +package com.example.gameofthrones.data.entities + +import androidx.room.TypeConverter +import com.google.gson.reflect.TypeToken +import com.google.gson.Gson +import java.lang.reflect.Type +class StringListTypeConverter { + private val gson = Gson() + + @TypeConverter + fun fromStringList(list: List?): String? { + return gson.toJson(list) + } + + @TypeConverter + fun toStringList(json: String?): List? { + val type: Type = object : TypeToken?>() {}.type + return gson.fromJson(json, type) + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/local/AppDatabase.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/local/AppDatabase.kt new file mode 100644 index 0000000..e1c0373 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/local/AppDatabase.kt @@ -0,0 +1,27 @@ +package com.example.gameofthrones.data.local + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import androidx.room.TypeConverters +import com.example.gameofthrones.data.entities.HouseGameOfThrones +import com.example.gameofthrones.data.entities.StringListTypeConverter + +@TypeConverters(StringListTypeConverter::class) +@Database(entities = [HouseGameOfThrones::class], version = 3, exportSchema = false) +abstract class AppDatabase: RoomDatabase() { + + abstract fun houseDao(): HouseGameOfThronesDao + companion object { + @Volatile private var instance: AppDatabase? = null + + fun getDatabase(context: Context): AppDatabase = + instance ?: synchronized(this) { instance ?: buildDatabase(context).also { instance = it } } + + private fun buildDatabase(appContext: Context) = + Room.databaseBuilder(appContext, AppDatabase::class.java, "houses") + .fallbackToDestructiveMigration() + .build() + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/local/HouseGameOfThronesDao.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/local/HouseGameOfThronesDao.kt new file mode 100644 index 0000000..908ab53 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/local/HouseGameOfThronesDao.kt @@ -0,0 +1,24 @@ +package com.example.gameofthrones.data.local + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.example.gameofthrones.data.entities.HouseGameOfThrones + +@Dao +interface HouseGameOfThronesDao { + + @Query("SELECT * FROM houses") + fun getAllHouses() : LiveData> + + @Query("SELECT * FROM houses WHERE id = :id") + fun getHouse(id: Int): LiveData + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(house: kotlin.collections.List) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(houses: HouseGameOfThrones) + +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/BaseDataSource.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/BaseDataSource.kt new file mode 100644 index 0000000..2c195cb --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/BaseDataSource.kt @@ -0,0 +1,26 @@ +package com.example.gameofthrones.data.remote + +import com.example.gameofthrones.util.Resource +import retrofit2.Response +import timber.log.Timber + +abstract class BaseDataSource { + + protected suspend fun getResult(call: suspend () -> Response): Resource { + try { + val response = call() + if (response.isSuccessful) { + val body = response.body() + if (body != null) return Resource.success(body) + } + return error(" ${response.code()} ${response.message()}") + } catch (e: Exception) { + return error(e.message ?: e.toString()) + } + } + + private fun error(message: String): Resource { + Timber.d(message) + return Resource.error("Network call has failed for a following reason: $message") + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/HouseRemoteDataSource.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/HouseRemoteDataSource.kt new file mode 100644 index 0000000..5e9cd28 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/HouseRemoteDataSource.kt @@ -0,0 +1,11 @@ +package com.example.gameofthrones.data.remote + +import javax.inject.Inject + +class HouseRemoteDataSource @Inject constructor( + private val houseService: HouseService +): BaseDataSource() { + + suspend fun getHouses() = getResult { houseService.getAllHouses() } + suspend fun getHouses(id: Int) = getResult { houseService.getHouse(id) } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/HouseService.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/HouseService.kt new file mode 100644 index 0000000..2cc217b --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/remote/HouseService.kt @@ -0,0 +1,15 @@ +package com.example.gameofthrones.data.remote + +import com.example.gameofthrones.data.entities.HouseGameOfThrones +import com.example.gameofthrones.data.entities.HouseList +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Path + +interface HouseService { + @GET("houses") + suspend fun getAllHouses() : Response> + + @GET("houses/{id}") + suspend fun getHouse(@Path("id") id: Int): Response +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/repository/HouseRepository.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/repository/HouseRepository.kt new file mode 100644 index 0000000..c2bfdd6 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/data/repository/HouseRepository.kt @@ -0,0 +1,25 @@ +package com.example.gameofthrones.data.repository + +import com.example.gameofthrones.data.local.HouseGameOfThronesDao +import com.example.gameofthrones.data.remote.HouseRemoteDataSource +import com.example.gameofthrones.util.performGetOperation +import javax.inject.Inject + +class HouseRepository @Inject +constructor( + private val remoteDataSource: HouseRemoteDataSource, + private val localDataSource: HouseGameOfThronesDao +) { + + fun getHouse(id: Int) = performGetOperation( + databaseQuery = { localDataSource.getHouse(id) }, + networkCall = { remoteDataSource.getHouses(id) }, + saveCallResult = { localDataSource.insert(it) } + ) + + fun getHouses() = performGetOperation( + databaseQuery = { localDataSource.getAllHouses() }, + networkCall = { remoteDataSource.getHouses() }, + saveCallResult = { localDataSource.insertAll(it) } + ) +} diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/di/AppModule.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/di/AppModule.kt new file mode 100644 index 0000000..4238442 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/di/AppModule.kt @@ -0,0 +1,55 @@ +package com.example.gameofthrones.di + +import android.content.Context +import com.example.gameofthrones.data.local.AppDatabase +import com.example.gameofthrones.data.local.HouseGameOfThronesDao +import com.example.gameofthrones.data.remote.HouseRemoteDataSource +import com.example.gameofthrones.data.remote.HouseService +import com.example.gameofthrones.data.repository.HouseRepository +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import javax.inject.Singleton + + +@Module +@InstallIn(SingletonComponent::class) +object AppModule { + + @Singleton + @Provides + fun provideRetrofit(gson: Gson) : Retrofit = Retrofit.Builder() + .baseUrl("https://anapioficeandfire.com/api/") + .addConverterFactory(GsonConverterFactory.create(gson)) + .build() + + @Provides + fun provideGson(): Gson = GsonBuilder().create() + + @Provides + fun provideHouseService(retrofit: Retrofit): HouseService = retrofit.create(HouseService::class.java) + + @Singleton + @Provides + fun provideHouseRemoteDataSource(houseService: HouseService) = HouseRemoteDataSource(houseService) + + @Singleton + @Provides + fun provideDatabase(@ApplicationContext appContext: Context) = AppDatabase.getDatabase(appContext) + + @Singleton + @Provides + fun provideHouseDao(db: AppDatabase) = db.houseDao() + + @Singleton + @Provides + fun provideRepository(remoteDataSource: HouseRemoteDataSource, + localDataSource: HouseGameOfThronesDao) = + HouseRepository(remoteDataSource, localDataSource) +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/HouseDetailsActivity.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/HouseDetailsActivity.kt new file mode 100644 index 0000000..8bc92c4 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/HouseDetailsActivity.kt @@ -0,0 +1,28 @@ +package com.example.gameofthrones.ui + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.os.Parcelable +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.gameofthrones.R +import com.example.gameofthrones.data.GameOfThronesResponsesItem + +class HouseDetailsActivity : AppCompatActivity() { + + companion object { + private val TAG = HouseDetailsActivity::class.java.simpleName + const val HOUSE = "house" + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_house_details) + + val house : Parcelable? = intent.getParcelableExtra(HOUSE) + + val textView = findViewById(R.id.tvurl) + textView.text = house?.toString() + + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/MainActivity.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/MainActivity.kt new file mode 100644 index 0000000..90a363a --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/MainActivity.kt @@ -0,0 +1,30 @@ +package com.example.gameofthrones.ui + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import androidx.navigation.NavController +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.AppBarConfiguration +import androidx.navigation.ui.setupWithNavController +import com.example.gameofthrones.R +import com.example.gameofthrones.databinding.ActivityMainBinding +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + + val navHostFragment: NavHostFragment = + supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment + val navController: NavController = navHostFragment.navController + + val appBarConfiguration: AppBarConfiguration = AppBarConfiguration(navController.graph) + binding.toolbar.setupWithNavController(navController, appBarConfiguration) + + } + +} + diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseAdapter.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseAdapter.kt new file mode 100644 index 0000000..d9b2a4a --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseAdapter.kt @@ -0,0 +1,56 @@ +package com.example.gameofthrones.ui.house + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.CircleCrop +import com.example.gameofthrones.data.entities.HouseGameOfThrones +import com.example.gameofthrones.databinding.ItemHouseBinding + + +class HouseAdapter(private val listener: HouseItemListener) : RecyclerView.Adapter() { + + interface HouseItemListener { + fun onClickedHouse(houseId: Int) + } + private val items = ArrayList() + + fun setItems(items: ArrayList) { + this.items.clear() + this.items.addAll(items) + notifyDataSetChanged() + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HouseViewHolder { + val binding: ItemHouseBinding = ItemHouseBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return HouseViewHolder(binding, listener) + } + override fun getItemCount(): Int = items.size + + override fun onBindViewHolder(holder: HouseViewHolder, position: Int) = holder.bind(items[position]) + } + +class HouseViewHolder(private val itemBinding: ItemHouseBinding, private val listener: HouseAdapter.HouseItemListener) : RecyclerView.ViewHolder(itemBinding.root), + View.OnClickListener { + + private lateinit var house: HouseGameOfThrones + + init { + itemBinding.root.setOnClickListener(this) + } + @SuppressLint("SetTextI18n") + fun bind(item: HouseGameOfThrones) { + this.house = item + itemBinding.tvName.text = item.name + Glide.with(itemBinding.root) + .load(item.overlord) + .transform(CircleCrop()) + .into(itemBinding.image) + } + override fun onClick(v: View?) { + house.id?.let { listener.onClickedHouse(it) } + } + +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseFragment.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseFragment.kt new file mode 100644 index 0000000..5a4afdf --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseFragment.kt @@ -0,0 +1,71 @@ +package com.example.gameofthrones.ui.house + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.core.os.bundleOf +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.gameofthrones.R +import androidx.navigation.fragment.findNavController +import com.example.gameofthrones.util.autoCleared +import dagger.hilt.android.AndroidEntryPoint +import com.example.gameofthrones.databinding.FragmentHouseBinding +import androidx.lifecycle.Observer +import com.example.gameofthrones.util.Resource + + +@AndroidEntryPoint +class HouseFragment : Fragment(), HouseAdapter.HouseItemListener { + + private var binding: FragmentHouseBinding by autoCleared() + private val viewModel: HouseViewModel by viewModels() + private lateinit var adapter: HouseAdapter + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = FragmentHouseBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupRecyclerView() + setupObservers() + } + + private fun setupRecyclerView() { + adapter = HouseAdapter(this) + binding.housesRv.layoutManager = LinearLayoutManager(requireContext()) + binding.housesRv.adapter = adapter + } + + private fun setupObservers() { + viewModel.houses.observe(viewLifecycleOwner, Observer { + when (it.status) { + Resource.Status.SUCCESS -> { + binding.progressBar.visibility = View.GONE + if (!it.data.isNullOrEmpty()) adapter.setItems(ArrayList(it.data)) + } + Resource.Status.ERROR -> + Toast.makeText(requireContext(), it.message, Toast.LENGTH_SHORT).show() + + Resource.Status.LOADING -> + binding.progressBar.visibility = View.VISIBLE + } + }) + } + + + override fun onClickedHouse(houseId: Int) { + findNavController().navigate( + R.id.action_houseFragment_to_houseDetailFragment, + bundleOf("id" to houseId) + ) + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseViewModel.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseViewModel.kt new file mode 100644 index 0000000..b42abf5 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/house/HouseViewModel.kt @@ -0,0 +1,18 @@ +package com.example.gameofthrones.ui.house + + +import androidx.lifecycle.ViewModel +import com.example.gameofthrones.data.repository.HouseRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import javax.inject.Inject + +@HiltViewModel +class HouseViewModel @Inject constructor( + private val repository: HouseRepository +) : ViewModel() { + + val houses = repository.getHouses() +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/housedetails/HouseDetailFragment.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/housedetails/HouseDetailFragment.kt new file mode 100644 index 0000000..a85c588 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/housedetails/HouseDetailFragment.kt @@ -0,0 +1,76 @@ +package com.example.gameofthrones.ui.housedetails + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.lifecycle.Observer +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.CircleCrop +import com.example.gameofthrones.R +import com.example.gameofthrones.data.entities.HouseGameOfThrones +import com.example.gameofthrones.databinding.FragmentHouseDetailBinding +import com.example.gameofthrones.util.Resource +import com.example.gameofthrones.util.autoCleared +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class HouseDetailFragment : Fragment(){ + + private var binding: FragmentHouseDetailBinding by autoCleared() + private val viewModel: HouseDetailsViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = FragmentHouseDetailBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + arguments?.getInt("id")?.let { viewModel.start(it) } + setupObservers() + } + + private fun setupObservers() { + viewModel.houses.observe(viewLifecycleOwner, Observer { + when (it.status) { + Resource.Status.SUCCESS -> { + bindHouse(it.data!!) + binding.progressBar.visibility = View.GONE + binding.houseCl.visibility = View.VISIBLE + } + + Resource.Status.ERROR -> + Toast.makeText(activity, it.message, Toast.LENGTH_SHORT).show() + + Resource.Status.LOADING -> { + binding.progressBar.visibility = View.VISIBLE + binding.houseCl.visibility = View.GONE + } + } + }) + } + + private fun bindHouse(houseDetail: HouseGameOfThrones) { + binding.name.text = houseDetail.name + binding.coatOfArms.text = houseDetail.coatOfArms + binding.currentLord.text = houseDetail.currentLord + binding.founded.text = houseDetail.founded + binding.founder.text = houseDetail.founder + binding.heir.text = houseDetail.heir + binding.diedOut.text = houseDetail.diedOut + binding.overlord.text = houseDetail.overlord + binding.region.text = houseDetail.region + binding.words.text = houseDetail.words + Glide.with(binding.root) + .load(houseDetail.url) + .transform(CircleCrop()) + .into(binding.image) + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/housedetails/HouseDetailsViewModel.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/housedetails/HouseDetailsViewModel.kt new file mode 100644 index 0000000..418d856 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/ui/housedetails/HouseDetailsViewModel.kt @@ -0,0 +1,31 @@ +package com.example.gameofthrones.ui.housedetails + + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.switchMap +import com.example.gameofthrones.data.entities.HouseGameOfThrones +import com.example.gameofthrones.data.repository.HouseRepository +import com.example.gameofthrones.util.Resource +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class HouseDetailsViewModel @Inject constructor( + private val repository: HouseRepository +) : ViewModel() { + + private val _id = MutableLiveData() + + private val _house = _id.switchMap { id -> + repository.getHouse(id) + } + val houses: LiveData> = _house + + + fun start(id: Int) { + _id.value = id + } + +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/AutoClearedValue.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/AutoClearedValue.kt new file mode 100644 index 0000000..ff40dff --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/AutoClearedValue.kt @@ -0,0 +1,40 @@ +package com.example.gameofthrones.util + +import androidx.fragment.app.Fragment +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +class AutoClearedValue (val fragment: Fragment) : ReadWriteProperty { + private var _value: T? = null + + init { + fragment.lifecycle.addObserver(object : DefaultLifecycleObserver { + override fun onCreate(owner: LifecycleOwner) { + fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner -> + viewLifecycleOwner?.lifecycle?.addObserver(object : DefaultLifecycleObserver { + override fun onDestroy(owner: LifecycleOwner) { + _value = null + } + }) + } + } + }) + } + + override fun getValue(thisRef: Fragment, property: KProperty<*>): T { + return _value ?: throw IllegalStateException( + "should never call auto-cleared-value get when it might not be available" + ) + } + + override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) { + _value = value + } +} + +/** + * Creates an [AutoClearedValue] associated with this fragment. + */ +fun Fragment.autoCleared() = AutoClearedValue(this) \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/Constants.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/Constants.kt new file mode 100644 index 0000000..0b09432 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/Constants.kt @@ -0,0 +1,7 @@ +package com.example.gameofthrones.util + +class Constants { + companion object { + const val BASE_URL = "https://anapioficeandfire.com/" + } +} \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/DataAccessStrategy.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/DataAccessStrategy.kt new file mode 100644 index 0000000..1051d64 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/DataAccessStrategy.kt @@ -0,0 +1,28 @@ +package com.example.gameofthrones.util + +import androidx.lifecycle.LiveData +import androidx.lifecycle.LiveDataScope +import androidx.lifecycle.liveData +import androidx.lifecycle.map +import com.example.gameofthrones.util.Resource.Status +import kotlinx.coroutines.Dispatchers + + +fun performGetOperation(databaseQuery: () -> LiveData, + networkCall: suspend () -> Resource, + saveCallResult: suspend (A) -> Unit): LiveData> = + liveData(Dispatchers.IO) { + emit(Resource.loading()) + val source = databaseQuery.invoke().map { Resource.success(it) } + emitSource(source) + + val responseStatus = networkCall.invoke() + if (responseStatus.status == Status.SUCCESS) { + saveCallResult(responseStatus.data!!) + + } else if (responseStatus.status == Status.ERROR) { + emit(Resource.error(responseStatus.message!!)) + emitSource(source) + } + } + diff --git a/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/Resource.kt b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/Resource.kt new file mode 100644 index 0000000..0e8c144 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/java/com/example/gameofthrones/util/Resource.kt @@ -0,0 +1,26 @@ +package com.example.gameofthrones.util + + +data class Resource(val status: Status, val data: T?, val message: String?) { + companion object { + fun success(data: T?): Resource { + return Resource(Status.SUCCESS, data, null) + } + + fun error(msg: String): Resource { + val data: T? = null + return Resource(Status.ERROR, data, msg) + } + + + fun loading(data: T? = null): Resource { + return Resource(Status.LOADING, data, null) + } + } + enum class Status { + SUCCESS, + ERROR, + LOADING + } +} + diff --git a/Mobile/GameOfThrones/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/Mobile/GameOfThrones/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/drawable/ic_launcher_background.xml b/Mobile/GameOfThrones/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mobile/GameOfThrones/app/src/main/res/layout/activity_house_details.xml b/Mobile/GameOfThrones/app/src/main/res/layout/activity_house_details.xml new file mode 100644 index 0000000..b81f71a --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/layout/activity_house_details.xml @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/layout/activity_main.xml b/Mobile/GameOfThrones/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..a67b24c --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/layout/fragment_house.xml b/Mobile/GameOfThrones/app/src/main/res/layout/fragment_house.xml new file mode 100644 index 0000000..9549909 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/layout/fragment_house.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/layout/fragment_house_detail.xml b/Mobile/GameOfThrones/app/src/main/res/layout/fragment_house_detail.xml new file mode 100644 index 0000000..69169e8 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/layout/fragment_house_detail.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/layout/item_game_of_thrones.xml b/Mobile/GameOfThrones/app/src/main/res/layout/item_game_of_thrones.xml new file mode 100644 index 0000000..e412ac4 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/layout/item_game_of_thrones.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/layout/item_house.xml b/Mobile/GameOfThrones/app/src/main/res/layout/item_house.xml new file mode 100644 index 0000000..446c331 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/layout/item_house.xml @@ -0,0 +1,32 @@ + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml b/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/Mobile/GameOfThrones/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/Mobile/GameOfThrones/app/src/main/res/navigation/nav_graph.xml b/Mobile/GameOfThrones/app/src/main/res/navigation/nav_graph.xml new file mode 100644 index 0000000..0ffc8fd --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/navigation/nav_graph.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values-land/dimens.xml b/Mobile/GameOfThrones/app/src/main/res/values-land/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values-land/dimens.xml @@ -0,0 +1,3 @@ + + 48dp + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values-night/themes.xml b/Mobile/GameOfThrones/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..5400b9b --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values-w1240dp/dimens.xml b/Mobile/GameOfThrones/app/src/main/res/values-w1240dp/dimens.xml new file mode 100644 index 0000000..d73f4a3 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values-w1240dp/dimens.xml @@ -0,0 +1,3 @@ + + 200dp + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values-w600dp/dimens.xml b/Mobile/GameOfThrones/app/src/main/res/values-w600dp/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values-w600dp/dimens.xml @@ -0,0 +1,3 @@ + + 48dp + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values/colors.xml b/Mobile/GameOfThrones/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values/dimens.xml b/Mobile/GameOfThrones/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..125df87 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values/dimens.xml @@ -0,0 +1,3 @@ + + 16dp + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values/strings.xml b/Mobile/GameOfThrones/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..4b67d87 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values/strings.xml @@ -0,0 +1,14 @@ + + GameOfThrones + HouseDetailsActivity + + First Fragment + Second Fragment + Next + Previous + + Hello first fragment + Hello second fragment. Arg: %1$s + + Hello blank fragment + \ No newline at end of file diff --git a/Mobile/GameOfThrones/app/src/main/res/values/themes.xml b/Mobile/GameOfThrones/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..d2b7ef4 --- /dev/null +++ b/Mobile/GameOfThrones/app/src/main/res/values/themes.xml @@ -0,0 +1,25 @@ + + + + + + +