Data classes and other retrofit logic added #12
							
								
								
									
										1
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
								
							
							
						
						| @@ -1,5 +1,6 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | ||||
|   <component name="GradleMigrationSettings" migrationVersion="1" /> | ||||
|   <component name="GradleSettings"> | ||||
|     <option name="linkedExternalProjectsSettings"> | ||||
|       <GradleProjectSettings> | ||||
|   | ||||
| @@ -56,4 +56,10 @@ dependencies { | ||||
|     androidTestImplementation(libs.androidx.ui.test.junit4) | ||||
|     debugImplementation(libs.androidx.ui.tooling) | ||||
|     debugImplementation(libs.androidx.ui.test.manifest) | ||||
|  | ||||
|     implementation(libs.retrofit) | ||||
|     implementation(libs.converter.gson) | ||||
|     implementation(libs.kotlinx.coroutines.android) | ||||
|     implementation(libs.kotlinx.coroutines.core) | ||||
|  | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/ic_launcher-playstore.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 36 KiB | 
| @@ -0,0 +1,22 @@ | ||||
| package ru.vendetti.bitcoin_summarizer | ||||
|  | ||||
| import retrofit2.Response | ||||
| import retrofit2.http.GET | ||||
| import retrofit2.http.Query | ||||
|  | ||||
| // Retrofit-API-интерфейс | ||||
| interface CryptoApiService { | ||||
|     // Получение индекса страха и жадности (по умолчанию за 30 дней) | ||||
|     @GET("fng/") | ||||
|     suspend fun getFearAndGreedIndex( | ||||
|         @Query("limit") limit: Int = 30 | ||||
|     ): Response<FearAndGreedResponse> | ||||
|  | ||||
|     // Получение глобальной информации | ||||
|     @GET("v1/global/") | ||||
|     suspend fun getGlobalData(): Response<GlobalResponse> | ||||
|  | ||||
|     // Получение данных Bitcoin | ||||
|     @GET("v1/ticker/bitcoin/") | ||||
|     suspend fun getBitcoinTicker(): Response<TickerResponse> | ||||
| } | ||||
| @@ -0,0 +1,58 @@ | ||||
| package ru.vendetti.bitcoin_summarizer | ||||
|  | ||||
| //Репозиторий для обработки запросов | ||||
| class CryptoRepository(private val apiService: CryptoApiService) { | ||||
|     /** | ||||
|      * Запрашивает данные для Bitcoin-тикера | ||||
|      */ | ||||
|     suspend fun fetchBitcoinTicker(): TickerResponse? { | ||||
|         return try { | ||||
|             val response = apiService.getBitcoinTicker() | ||||
|             if (response.isSuccessful) { | ||||
|                 response.body() | ||||
|             } else { | ||||
|                 println("Ошибка запроса Bitcoin Ticker: ${response.code()}") | ||||
|                 null | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|             println("Exception при получении Bitcoin Ticker: ${e.localizedMessage}") | ||||
|             null | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Запрашивает глобальные данные крипторынка | ||||
|      */ | ||||
|     suspend fun fetchGlobalData(): GlobalResponse? { | ||||
|         return try { | ||||
|             val response = apiService.getGlobalData() | ||||
|             if (response.isSuccessful) { | ||||
|                 response.body() | ||||
|             } else { | ||||
|                 println("Ошибка запроса Global Data: ${response.code()}") | ||||
|                 null | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|             println("Exception при получении Global Data: ${e.localizedMessage}") | ||||
|             null | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Запрашивает индекс страха и жадности за указанный период (по умолчанию 30 дней) | ||||
|      */ | ||||
|     suspend fun fetchFearAndGreedData(limit: Int = 30): FearAndGreedResponse? { | ||||
|         return try { | ||||
|             val response = apiService.getFearAndGreedIndex(limit) | ||||
|             if (response.isSuccessful) { | ||||
|                 response.body() | ||||
|             } else { | ||||
|                 println("Ошибка запроса Fear & Greed Index: ${response.code()}") | ||||
|                 null | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|             println("Exception при получении Fear & Greed Index: ${e.localizedMessage}") | ||||
|             null | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| package ru.vendetti.bitcoin_summarizer | ||||
|  | ||||
| import com.google.gson.annotations.SerializedName | ||||
|  | ||||
| // Обёртка для данных (тут вложенность есть и это API v2, а не v1, поэтому чуть сложнее структура, чем в GlobalResponse.kt) | ||||
| data class FearAndGreedResponse( | ||||
|     @SerializedName("name") | ||||
|     val name: String, | ||||
|     @SerializedName("data") | ||||
|     val dataList: List<FearAndGreedData> | ||||
| ) | ||||
|  | ||||
| // Сами данные | ||||
| data class FearAndGreedData( | ||||
|     @SerializedName("value") | ||||
|     val value: String, | ||||
|     @SerializedName("value_classification") | ||||
|     val valueClassification: String, | ||||
|     @SerializedName("timestamp") | ||||
|     val timestamp: String, | ||||
|     @SerializedName("time_until_update") | ||||
|     val timeUntilUpdate: String | ||||
| ) | ||||
| @@ -0,0 +1,15 @@ | ||||
| package ru.vendetti.bitcoin_summarizer | ||||
|  | ||||
| import com.google.gson.annotations.SerializedName | ||||
|  | ||||
| // Обёртка для данных | ||||
| data class GlobalResponse( | ||||
|     val data: GlobalData | ||||
| ) | ||||
|  | ||||
| // Сами данные | ||||
| data class GlobalData( | ||||
|     @SerializedName("active_cryptocurrencies") val activeCryptocurrencies: String, | ||||
|     @SerializedName("total_market_cap_usd") val totalMarketCapUsd: String, | ||||
|     @SerializedName("total_24h_volume_usd") val total24hVolumeUsd: String | ||||
| ) | ||||
| @@ -0,0 +1,16 @@ | ||||
| package ru.vendetti.bitcoin_summarizer | ||||
|  | ||||
| import retrofit2.Retrofit | ||||
| import retrofit2.converter.gson.GsonConverterFactory | ||||
|  | ||||
| object RetrofitClient { | ||||
|     private const val BASE_URL = "https://api.alternative.me/" | ||||
|  | ||||
|     val apiService: CryptoApiService by lazy { | ||||
|         Retrofit.Builder() | ||||
|             .baseUrl(BASE_URL) | ||||
|             .addConverterFactory(GsonConverterFactory.create()) | ||||
|             .build() | ||||
|             .create(CryptoApiService::class.java) | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,25 @@ | ||||
| package ru.vendetti.bitcoin_summarizer | ||||
|  | ||||
| import com.google.gson.annotations.SerializedName | ||||
|  | ||||
| // Обёртка для данных (тут json-массив с одним элементом, поэтому выглядит так) | ||||
| typealias TickerResponse = List<TickerData> | ||||
|  | ||||
| // Сами данные | ||||
| data class TickerData( | ||||
|     val id: String, | ||||
|     val name: String, | ||||
|     val symbol: String, | ||||
|     val rank: String, | ||||
|     @SerializedName("price_usd") val priceUsd: String, | ||||
|     @SerializedName("price_btc") val priceBtc: String, | ||||
|     @SerializedName("24h_volume_usd") val volume24hUsd: String, | ||||
|     @SerializedName("market_cap_usd") val marketCapUsd: String, | ||||
|     @SerializedName("available_supply") val availableSupply: String, | ||||
|     @SerializedName("total_supply") val totalSupply: String, | ||||
|     @SerializedName("max_supply") val maxSupply: String?, | ||||
|     @SerializedName("percent_change_1h") val percentChange1h: String, | ||||
|     @SerializedName("percent_change_24h") val percentChange24h: String, | ||||
|     @SerializedName("percent_change_7d") val percentChange7d: String, | ||||
|     @SerializedName("last_updated") val lastUpdated: String | ||||
| ) | ||||
							
								
								
									
										6
									
								
								app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <background android:drawable="@color/ic_launcher_background"/> | ||||
|     <foreground android:drawable="@mipmap/ic_launcher_foreground"/> | ||||
|     <monochrome android:drawable="@mipmap/ic_launcher_foreground"/> | ||||
| </adaptive-icon> | ||||
							
								
								
									
										6
									
								
								app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <background android:drawable="@color/ic_launcher_background"/> | ||||
|     <foreground android:drawable="@mipmap/ic_launcher_foreground"/> | ||||
|     <monochrome android:drawable="@mipmap/ic_launcher_foreground"/> | ||||
| </adaptive-icon> | ||||
| @@ -1,6 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <background android:drawable="@drawable/ic_launcher_background" /> | ||||
|     <foreground android:drawable="@drawable/ic_launcher_foreground" /> | ||||
|     <monochrome android:drawable="@drawable/ic_launcher_foreground" /> | ||||
| </adaptive-icon> | ||||
| @@ -1,6 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <background android:drawable="@drawable/ic_launcher_background" /> | ||||
|     <foreground android:drawable="@drawable/ic_launcher_foreground" /> | ||||
|     <monochrome android:drawable="@drawable/ic_launcher_foreground" /> | ||||
| </adaptive-icon> | ||||
| Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.3 KiB | 
| Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.2 KiB | 
| Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.6 KiB | 
| Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.6 KiB | 
| Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.1 KiB | 
| Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 5.5 KiB | 
| Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 5.0 KiB | 
| Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 8.3 KiB | 
| Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 6.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.7 KiB | 
| Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										4
									
								
								app/src/main/res/values/ic_launcher_background.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,4 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <color name="ic_launcher_background">#FFFFFF</color> | ||||
| </resources> | ||||
| @@ -1,16 +1,21 @@ | ||||
| [versions] | ||||
| agp = "8.8.1" | ||||
| converterGson = "2.9.0" | ||||
| kotlin = "2.0.0" | ||||
| coreKtx = "1.10.1" | ||||
| junit = "4.13.2" | ||||
| junitVersion = "1.1.5" | ||||
| espressoCore = "3.5.1" | ||||
| kotlinxCoroutinesAndroid = "1.7.1" | ||||
| kotlinxCoroutinesCore = "1.7.1" | ||||
| lifecycleRuntimeKtx = "2.6.1" | ||||
| activityCompose = "1.8.0" | ||||
| composeBom = "2024.04.01" | ||||
| retrofit = "2.9.0" | ||||
|  | ||||
| [libraries] | ||||
| androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } | ||||
| converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" } | ||||
| junit = { group = "junit", name = "junit", version.ref = "junit" } | ||||
| androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } | ||||
| androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } | ||||
| @@ -24,6 +29,9 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin | ||||
| androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } | ||||
| androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } | ||||
| androidx-material3 = { group = "androidx.compose.material3", name = "material3" } | ||||
| kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" } | ||||
| kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" } | ||||
| retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } | ||||
|  | ||||
| [plugins] | ||||
| android-application = { id = "com.android.application", version.ref = "agp" } | ||||
|   | ||||