Compare commits
	
		
			10 Commits
		
	
	
		
			8c69116171
			...
			c64a8d1f73
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					
						
						
							
						
						c64a8d1f73
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						dd3786166c
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						e072f88d69
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						dec32634b5
	
				 | 
					
					
						||
| 
						 | 
					e7b9269ab0 | ||
| 
						 | 
					
						
						
							
						
						13dc50afe8
	
				 | 
					
					
						||
| 
						 | 
					9b8af28f47 | ||
| 
						 | 
					
						
						
							
						
						09f9b2c5cf
	
				 | 
					
					
						||
| 
						 | 
					6b7cd89f86 | ||
| 
						 | 
					
						
						
							
						
						8690ed006e
	
				 | 
					
					
						
@@ -25,6 +25,7 @@ android {
 | 
				
			|||||||
        release {
 | 
					        release {
 | 
				
			||||||
            isMinifyEnabled = false
 | 
					            isMinifyEnabled = false
 | 
				
			||||||
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
 | 
					            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
 | 
				
			||||||
 | 
					            signingConfig = signingConfigs.getByName("debug")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    compileOptions {
 | 
					    compileOptions {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
    xmlns:tools="http://schemas.android.com/tools">
 | 
					    xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
 | 
					    package="com.ti.mobpo">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <uses-permission android:name="android.permission.INTERNET" />
 | 
					    <uses-permission android:name="android.permission.INTERNET" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <application
 | 
					    <application
 | 
				
			||||||
        android:name=".PokeSearch"
 | 
					 | 
				
			||||||
        android:allowBackup="true"
 | 
					        android:allowBackup="true"
 | 
				
			||||||
        android:enableOnBackInvokedCallback="true"
 | 
					        android:enableOnBackInvokedCallback="true"
 | 
				
			||||||
        android:dataExtractionRules="@xml/data_extraction_rules"
 | 
					        android:dataExtractionRules="@xml/data_extraction_rules"
 | 
				
			||||||
@@ -15,6 +16,8 @@
 | 
				
			|||||||
        android:supportsRtl="true"
 | 
					        android:supportsRtl="true"
 | 
				
			||||||
        android:theme="@style/Theme.MobileSecurity"
 | 
					        android:theme="@style/Theme.MobileSecurity"
 | 
				
			||||||
        tools:targetApi="31">
 | 
					        tools:targetApi="31">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <!-- Specify your main activity here -->
 | 
				
			||||||
        <activity
 | 
					        <activity
 | 
				
			||||||
            android:name=".MainActivity"
 | 
					            android:name=".MainActivity"
 | 
				
			||||||
            android:exported="true"
 | 
					            android:exported="true"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/ic_launcher-playstore.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 19 KiB  | 
@@ -1,29 +1,33 @@
 | 
				
			|||||||
package com.ti.mobpo
 | 
					package com.ti.mobpo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.lifecycle.ViewModelProvider
 | 
					 | 
				
			||||||
import androidx.lifecycle.viewmodel.CreationExtras
 | 
					 | 
				
			||||||
import androidx.lifecycle.viewmodel.initializer
 | 
					import androidx.lifecycle.viewmodel.initializer
 | 
				
			||||||
import androidx.lifecycle.viewmodel.viewModelFactory
 | 
					import androidx.lifecycle.viewmodel.viewModelFactory
 | 
				
			||||||
 | 
					import com.ti.mobpo.data.AppContainer
 | 
				
			||||||
 | 
					import com.ti.mobpo.ui.util.FeatureManager
 | 
				
			||||||
import com.ti.mobpo.ui.viewmodels.FavouritesViewModel
 | 
					import com.ti.mobpo.ui.viewmodels.FavouritesViewModel
 | 
				
			||||||
import com.ti.mobpo.ui.viewmodels.PokeSearchViewModel
 | 
					import com.ti.mobpo.ui.viewmodels.PokeSearchViewModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
object AppViewModelProvider {
 | 
					object AppViewModelProvider {
 | 
				
			||||||
    val Factory = viewModelFactory {
 | 
					    lateinit var appContainer: AppContainer
 | 
				
			||||||
        initializer {
 | 
					    lateinit var featureManager: FeatureManager
 | 
				
			||||||
            PokeSearchViewModel(
 | 
					 | 
				
			||||||
                pokesearchApplication().appContainer.favouritesRepository
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun initialize(appContainer: AppContainer, featureManager: FeatureManager) {
 | 
				
			||||||
 | 
					        this.appContainer = appContainer
 | 
				
			||||||
 | 
					        this.featureManager = featureManager
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        initializer {
 | 
					    val Factory = viewModelFactory {
 | 
				
			||||||
 | 
					        initializer { ->
 | 
				
			||||||
 | 
					            PokeSearchViewModel(
 | 
				
			||||||
 | 
					                appContainer.favouritesRepository
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        initializer { ->
 | 
				
			||||||
            FavouritesViewModel(
 | 
					            FavouritesViewModel(
 | 
				
			||||||
                pokesearchApplication().appContainer.favouritesRepository, pokesearchApplication().featureManager
 | 
					                appContainer.favouritesRepository,
 | 
				
			||||||
 | 
					                featureManager
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
fun CreationExtras.pokesearchApplication(): PokeSearch =
 | 
					 | 
				
			||||||
    (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as PokeSearch)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,17 +4,39 @@ import android.annotation.SuppressLint
 | 
				
			|||||||
import android.os.Bundle
 | 
					import android.os.Bundle
 | 
				
			||||||
import androidx.activity.ComponentActivity
 | 
					import androidx.activity.ComponentActivity
 | 
				
			||||||
import androidx.activity.compose.setContent
 | 
					import androidx.activity.compose.setContent
 | 
				
			||||||
 | 
					import com.ti.mobpo.data.AppContainer
 | 
				
			||||||
 | 
					import com.ti.mobpo.data.AppDataContainer
 | 
				
			||||||
import com.ti.mobpo.ui.Navigation
 | 
					import com.ti.mobpo.ui.Navigation
 | 
				
			||||||
import com.ti.mobpo.ui.theme.MobileSecurityTheme
 | 
					import com.ti.mobpo.ui.theme.MobileSecurityTheme
 | 
				
			||||||
 | 
					import com.ti.mobpo.ui.util.FeatureManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MainActivity : ComponentActivity() {
 | 
					class MainActivity : ComponentActivity() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lateinit var appContainer: AppContainer
 | 
				
			||||||
 | 
					        private set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lateinit var featureManager: FeatureManager
 | 
				
			||||||
 | 
					        private set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
 | 
					    @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
 | 
				
			||||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
					    override fun onCreate(savedInstanceState: Bundle?) {
 | 
				
			||||||
        super.onCreate(savedInstanceState)
 | 
					        super.onCreate(savedInstanceState)
 | 
				
			||||||
        setContent {
 | 
					        setContent {
 | 
				
			||||||
            MobileSecurityTheme {
 | 
					            MobileSecurityTheme {
 | 
				
			||||||
                Navigation()
 | 
					                Navigation(this@MainActivity)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        appContainer = createAppContainer()
 | 
				
			||||||
 | 
					        featureManager = createFeatrureManager()
 | 
				
			||||||
 | 
					        AppViewModelProvider.initialize(appContainer, featureManager)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun createAppContainer(): AppContainer {
 | 
				
			||||||
 | 
					        return AppDataContainer(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun createFeatrureManager(): FeatureManager {
 | 
				
			||||||
 | 
					        return FeatureManager(this)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,28 +0,0 @@
 | 
				
			|||||||
package com.ti.mobpo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import android.app.Application
 | 
					 | 
				
			||||||
import com.ti.mobpo.data.AppContainer
 | 
					 | 
				
			||||||
import com.ti.mobpo.data.AppDataContainer
 | 
					 | 
				
			||||||
import com.ti.mobpo.ui.util.FeatureManager
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class PokeSearch : Application() {
 | 
					 | 
				
			||||||
    lateinit var appContainer: AppContainer
 | 
					 | 
				
			||||||
        private set
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    lateinit var featureManager: FeatureManager
 | 
					 | 
				
			||||||
        private set
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun onCreate() {
 | 
					 | 
				
			||||||
        super.onCreate()
 | 
					 | 
				
			||||||
        appContainer = createAppContainer()
 | 
					 | 
				
			||||||
        featureManager = createFeatrureManager()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun createAppContainer(): AppContainer {
 | 
					 | 
				
			||||||
        return AppDataContainer(this)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun createFeatrureManager(): FeatureManager {
 | 
					 | 
				
			||||||
        return FeatureManager(this)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -31,13 +31,14 @@ import androidx.navigation.compose.composable
 | 
				
			|||||||
import androidx.navigation.compose.currentBackStackEntryAsState
 | 
					import androidx.navigation.compose.currentBackStackEntryAsState
 | 
				
			||||||
import androidx.navigation.compose.rememberNavController
 | 
					import androidx.navigation.compose.rememberNavController
 | 
				
			||||||
import com.ti.mobpo.AppViewModelProvider
 | 
					import com.ti.mobpo.AppViewModelProvider
 | 
				
			||||||
 | 
					import com.ti.mobpo.MainActivity
 | 
				
			||||||
import com.ti.mobpo.ui.screens.FavoritesScreen
 | 
					import com.ti.mobpo.ui.screens.FavoritesScreen
 | 
				
			||||||
import com.ti.mobpo.ui.screens.PokeSearchScreen
 | 
					import com.ti.mobpo.ui.screens.PokeSearchScreen
 | 
				
			||||||
import com.ti.mobpo.ui.viewmodels.FavouritesViewModel
 | 
					import com.ti.mobpo.ui.viewmodels.FavouritesViewModel
 | 
				
			||||||
import com.ti.mobpo.ui.viewmodels.PokeSearchViewModel
 | 
					import com.ti.mobpo.ui.viewmodels.PokeSearchViewModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
fun Navigation() {
 | 
					fun Navigation(activity: MainActivity) {
 | 
				
			||||||
    val items = listOf(
 | 
					    val items = listOf(
 | 
				
			||||||
        BottomNavigationItem(
 | 
					        BottomNavigationItem(
 | 
				
			||||||
            title = "Home",
 | 
					            title = "Home",
 | 
				
			||||||
@@ -66,6 +67,8 @@ fun Navigation() {
 | 
				
			|||||||
    val pokeSearchVM = viewModel<PokeSearchViewModel>(factory = AppViewModelProvider.Factory)
 | 
					    val pokeSearchVM = viewModel<PokeSearchViewModel>(factory = AppViewModelProvider.Factory)
 | 
				
			||||||
    val favoritesVM = viewModel<FavouritesViewModel>(factory = AppViewModelProvider.Factory)
 | 
					    val favoritesVM = viewModel<FavouritesViewModel>(factory = AppViewModelProvider.Factory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Scaffold (
 | 
					    Scaffold (
 | 
				
			||||||
        bottomBar = {
 | 
					        bottomBar = {
 | 
				
			||||||
            NavigationBar {
 | 
					            NavigationBar {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
package com.ti.mobpo.ui.screens
 | 
					package com.ti.mobpo.ui.screens
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.foundation.clickable
 | 
				
			||||||
import androidx.compose.foundation.layout.Arrangement
 | 
					import androidx.compose.foundation.layout.Arrangement
 | 
				
			||||||
import androidx.compose.foundation.layout.Column
 | 
					import androidx.compose.foundation.layout.Column
 | 
				
			||||||
import androidx.compose.foundation.layout.Spacer
 | 
					import androidx.compose.foundation.layout.Spacer
 | 
				
			||||||
@@ -16,6 +17,8 @@ import com.ti.mobpo.ui.viewmodels.FavouritesViewModel
 | 
				
			|||||||
import androidx.compose.foundation.layout.height
 | 
					import androidx.compose.foundation.layout.height
 | 
				
			||||||
import androidx.compose.foundation.layout.padding
 | 
					import androidx.compose.foundation.layout.padding
 | 
				
			||||||
import androidx.compose.foundation.lazy.grid.items
 | 
					import androidx.compose.foundation.lazy.grid.items
 | 
				
			||||||
 | 
					import androidx.compose.material3.AlertDialog
 | 
				
			||||||
 | 
					import androidx.compose.material3.Button
 | 
				
			||||||
import androidx.compose.runtime.LaunchedEffect
 | 
					import androidx.compose.runtime.LaunchedEffect
 | 
				
			||||||
import androidx.compose.ui.Modifier
 | 
					import androidx.compose.ui.Modifier
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,6 +44,29 @@ fun Favorites(favoritesViewModel: FavouritesViewModel) {
 | 
				
			|||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        Spacer(modifier = Modifier.height(16.dp))
 | 
					        Spacer(modifier = Modifier.height(16.dp))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (favoritesViewModel.accessCheckFailed.value) {
 | 
				
			||||||
 | 
					            AlertDialog(
 | 
				
			||||||
 | 
					                onDismissRequest = {
 | 
				
			||||||
 | 
					                    favoritesViewModel.accessCheckFailed.value = false
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                title = {
 | 
				
			||||||
 | 
					                    Text("Access Denied")
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                text = {
 | 
				
			||||||
 | 
					                    Text("You do not have access to this feature.")
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                confirmButton = {
 | 
				
			||||||
 | 
					                    Button(
 | 
				
			||||||
 | 
					                        onClick = {
 | 
				
			||||||
 | 
					                            favoritesViewModel.accessCheckFailed.value = false
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    ) {
 | 
				
			||||||
 | 
					                        Text("OK")
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        favorites?.let { favoritesList ->
 | 
					        favorites?.let { favoritesList ->
 | 
				
			||||||
            if (favoritesList.isNotEmpty()) {
 | 
					            if (favoritesList.isNotEmpty()) {
 | 
				
			||||||
                LazyVerticalGrid(
 | 
					                LazyVerticalGrid(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
package com.ti.mobpo.ui.viewmodels
 | 
					package com.ti.mobpo.ui.viewmodels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.runtime.MutableState
 | 
				
			||||||
 | 
					import androidx.compose.runtime.mutableStateOf
 | 
				
			||||||
import androidx.lifecycle.ViewModel
 | 
					import androidx.lifecycle.ViewModel
 | 
				
			||||||
import androidx.lifecycle.viewModelScope
 | 
					import androidx.lifecycle.viewModelScope
 | 
				
			||||||
import com.ti.mobpo.data.Favourite
 | 
					import com.ti.mobpo.data.Favourite
 | 
				
			||||||
@@ -17,15 +19,22 @@ import kotlinx.coroutines.flow.stateIn
 | 
				
			|||||||
import kotlinx.coroutines.launch
 | 
					import kotlinx.coroutines.launch
 | 
				
			||||||
import java.io.IOException
 | 
					import java.io.IOException
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FavouritesViewModel(private val favouritesRepository: FavouritesRepository, featureManager: FeatureManager) : ViewModel() {
 | 
					class FavouritesViewModel(private val favouritesRepository: FavouritesRepository,
 | 
				
			||||||
    private val service = PokeApi.retrofitService
 | 
					                          private val featureManager: FeatureManager
 | 
				
			||||||
 | 
					) : ViewModel() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val service = PokeApi.retrofitService
 | 
				
			||||||
    private val _pokemonDetails = MutableStateFlow<List<PokemonDetails>?>(null)
 | 
					    private val _pokemonDetails = MutableStateFlow<List<PokemonDetails>?>(null)
 | 
				
			||||||
    val pokemonDetails: StateFlow<List<PokemonDetails>?> = _pokemonDetails.asStateFlow()
 | 
					    val pokemonDetails: StateFlow<List<PokemonDetails>?> = _pokemonDetails.asStateFlow()
 | 
				
			||||||
 | 
					    val accessCheckFailed: MutableState<Boolean> = mutableStateOf(false)
 | 
				
			||||||
    fun loadFavourites() {
 | 
					    fun loadFavourites() {
 | 
				
			||||||
 | 
					        // featureManager.setPaidFeatureEnabled(false) enable and disable acccess
 | 
				
			||||||
        // Ugly workaround to make sure all the favourites are loaded before displaying them
 | 
					        // Ugly workaround to make sure all the favourites are loaded before displaying them
 | 
				
			||||||
        viewModelScope.launch {
 | 
					        viewModelScope.launch {
 | 
				
			||||||
 | 
					            if(!featureManager.hasAccessToPaidFeature()) {
 | 
				
			||||||
 | 
					                accessCheckFailed.value = true
 | 
				
			||||||
 | 
					                return@launch
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                val favouritesList: StateFlow<FavouriteUiState> =
 | 
					                val favouritesList: StateFlow<FavouriteUiState> =
 | 
				
			||||||
                    favouritesRepository.getAllItems().map { FavouriteUiState(it) }
 | 
					                    favouritesRepository.getAllItems().map { FavouriteUiState(it) }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,7 @@ class PokeSearchViewModel(private val favouritesRepository: FavouritesRepository
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                val detailsList = mutableListOf<PokemonDetails>()
 | 
					                val detailsList = mutableListOf<PokemonDetails>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (firstIndex != null && lastIndex != null) {
 | 
					                if (firstIndex != null && lastIndex != null && firstIndex != -1 && lastIndex != -1) {
 | 
				
			||||||
                    val endIndex = minOf(firstIndex + SHOW_LIMIT, lastIndex + 1)
 | 
					                    val endIndex = minOf(firstIndex + SHOW_LIMIT, lastIndex + 1)
 | 
				
			||||||
                    val startIndex = maxOf(firstIndex, endIndex - SHOW_LIMIT)
 | 
					                    val startIndex = maxOf(firstIndex, endIndex - SHOW_LIMIT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,170 +1,74 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
 | 
					<vector
 | 
				
			||||||
    android:width="108dp"
 | 
					 | 
				
			||||||
    android:height="108dp"
 | 
					    android:height="108dp"
 | 
				
			||||||
 | 
					    android:width="108dp"
 | 
				
			||||||
 | 
					    android:viewportHeight="108"
 | 
				
			||||||
    android:viewportWidth="108"
 | 
					    android:viewportWidth="108"
 | 
				
			||||||
    android:viewportHeight="108">
 | 
					    xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
    <path
 | 
					    <path android:fillColor="#3DDC84"
 | 
				
			||||||
        android:fillColor="#3DDC84"
 | 
					          android:pathData="M0,0h108v108h-108z"/>
 | 
				
			||||||
        android:pathData="M0,0h108v108h-108z" />
 | 
					    <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
 | 
				
			||||||
    <path
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					    <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
 | 
				
			||||||
        android:pathData="M9,0L9,108"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					    <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
    <path
 | 
					    <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:pathData="M19,0L19,108"
 | 
					    <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					    <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
 | 
				
			||||||
    <path
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					    <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
 | 
				
			||||||
        android:pathData="M29,0L29,108"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					    <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
    <path
 | 
					    <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:pathData="M39,0L39,108"
 | 
					    <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
 | 
				
			||||||
    <path
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
 | 
				
			||||||
        android:pathData="M49,0L49,108"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
    <path
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:pathData="M59,0L59,108"
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
 | 
				
			||||||
    <path
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
 | 
				
			||||||
        android:pathData="M69,0L69,108"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
    <path
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:pathData="M79,0L79,108"
 | 
					    <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					    <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
 | 
				
			||||||
    <path
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					    <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
 | 
				
			||||||
        android:pathData="M89,0L89,108"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					    <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
    <path
 | 
					    <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:pathData="M99,0L99,108"
 | 
					    <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					    <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
 | 
				
			||||||
    <path
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					    <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
 | 
				
			||||||
        android:pathData="M0,9L108,9"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					    <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
    <path
 | 
					    <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:pathData="M0,19L108,19"
 | 
					    <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					    <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
 | 
				
			||||||
    <path
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					    <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
 | 
				
			||||||
        android:pathData="M0,29L108,29"
 | 
					          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M0,39L108,39"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M0,49L108,49"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M0,59L108,59"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M0,69L108,69"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M0,79L108,79"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M0,89L108,89"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M0,99L108,99"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M19,29L89,29"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M19,39L89,39"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M19,49L89,49"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M19,59L89,59"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M19,69L89,69"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M19,79L89,79"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M29,19L29,89"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M39,19L39,89"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M49,19L49,89"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M59,19L59,89"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M69,19L69,89"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
        android:fillColor="#00000000"
 | 
					 | 
				
			||||||
        android:pathData="M79,19L79,89"
 | 
					 | 
				
			||||||
        android:strokeWidth="0.8"
 | 
					 | 
				
			||||||
        android:strokeColor="#33FFFFFF" />
 | 
					 | 
				
			||||||
</vector>
 | 
					</vector>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
 | 
					<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
    <background android:drawable="@drawable/ic_launcher_background" />
 | 
					    <background android:drawable="@drawable/ic_launcher_background"/>
 | 
				
			||||||
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
 | 
					    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
 | 
				
			||||||
    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
 | 
					 | 
				
			||||||
</adaptive-icon>
 | 
					</adaptive-icon>
 | 
				
			||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
 | 
					<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
    <background android:drawable="@drawable/ic_launcher_background" />
 | 
					    <background android:drawable="@drawable/ic_launcher_background"/>
 | 
				
			||||||
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
 | 
					    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
 | 
				
			||||||
    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
 | 
					 | 
				
			||||||
</adaptive-icon>
 | 
					</adaptive-icon>
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB  | 
| 
		 Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.7 KiB  | 
| 
		 Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 1.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.5 KiB  | 
| 
		 Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB  | 
| 
		 Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB  | 
| 
		 Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 6.4 KiB  | 
| 
		 Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8.8 KiB  | 
@@ -2,6 +2,7 @@
 | 
				
			|||||||
plugins {
 | 
					plugins {
 | 
				
			||||||
    alias(libs.plugins.androidApplication) apply false
 | 
					    alias(libs.plugins.androidApplication) apply false
 | 
				
			||||||
    alias(libs.plugins.jetbrainsKotlinAndroid) apply false
 | 
					    alias(libs.plugins.jetbrainsKotlinAndroid) apply false
 | 
				
			||||||
 | 
					    id("com.google.devtools.ksp") version "1.9.20-1.0.14"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
buildscript {
 | 
					buildscript {
 | 
				
			||||||
 
 | 
				
			|||||||