Бэкенд-распознавание асинхронное (чанк аудио + поллинг ~до 18с) — точечно поднимаем readTimeout до 30с только для пути shazam/recognize (базовый 10с мал). Bump backend submodule (двухстадийный флоу shazam-api.com). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
253 lines
9.3 KiB
Kotlin
253 lines
9.3 KiB
Kotlin
package com.radiola.di
|
||
|
||
import android.content.Context
|
||
import androidx.room.Room
|
||
import com.radiola.data.local.AppDatabase
|
||
import com.radiola.data.local.LocalStationDataSource
|
||
import com.radiola.data.local.MIGRATION_1_2
|
||
import com.radiola.data.local.MIGRATION_2_3
|
||
import com.radiola.data.local.MIGRATION_3_4
|
||
import com.radiola.data.local.MIGRATION_4_5
|
||
import com.radiola.data.local.MIGRATION_5_6
|
||
import com.radiola.data.local.MIGRATION_6_7
|
||
import com.radiola.data.local.MIGRATION_7_8
|
||
import com.radiola.data.local.dao.AlarmDao
|
||
import com.radiola.data.remote.AuthInterceptor
|
||
import com.radiola.data.remote.LrcLibApi
|
||
import com.radiola.data.remote.LoveApi
|
||
import com.radiola.data.remote.RecordApi
|
||
import com.radiola.data.remote.RadiolaApi
|
||
import com.radiola.data.repository.AuthRepositoryImpl
|
||
import com.radiola.data.repository.ChartsRepositoryImpl
|
||
import com.radiola.data.repository.FavoritesRepositoryImpl
|
||
import com.radiola.data.repository.LyricsRepositoryImpl
|
||
import com.radiola.data.repository.NowPlayingRepositoryImpl
|
||
import com.radiola.data.repository.RecordingRepositoryImpl
|
||
import com.radiola.data.repository.RegionRepositoryImpl
|
||
import com.radiola.data.repository.SettingsRepositoryImpl
|
||
import com.radiola.data.repository.StationRepositoryImpl
|
||
import com.radiola.data.repository.SyncRepositoryImpl
|
||
import com.radiola.data.repository.RecognizedTrackRepositoryImpl
|
||
import com.radiola.data.repository.ShazamRepositoryImpl
|
||
import com.radiola.data.repository.TrackHistoryRepositoryImpl
|
||
import com.radiola.domain.repository.AuthRepository
|
||
import com.radiola.domain.repository.RecognizedTrackRepository
|
||
import com.radiola.domain.repository.ShazamRepository
|
||
import com.radiola.domain.repository.ChartsRepository
|
||
import com.radiola.domain.repository.FavoritesRepository
|
||
import com.radiola.domain.repository.LyricsRepository
|
||
import com.radiola.domain.repository.SyncRepository
|
||
import com.radiola.domain.repository.NowPlayingRepository
|
||
import com.radiola.domain.repository.RecordingRepository
|
||
import com.radiola.domain.repository.RegionRepository
|
||
import com.radiola.domain.repository.SettingsRepository
|
||
import com.radiola.domain.repository.StationRepository
|
||
import com.radiola.domain.repository.TrackHistoryRepository
|
||
import dagger.Module
|
||
import dagger.Provides
|
||
import dagger.hilt.InstallIn
|
||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||
import dagger.hilt.components.SingletonComponent
|
||
import kotlinx.serialization.json.Json
|
||
import okhttp3.MediaType.Companion.toMediaType
|
||
import okhttp3.OkHttpClient
|
||
import okhttp3.logging.HttpLoggingInterceptor
|
||
import retrofit2.Retrofit
|
||
import retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||
import javax.inject.Named
|
||
import javax.inject.Singleton
|
||
|
||
@Module
|
||
@InstallIn(SingletonComponent::class)
|
||
object AppModule {
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideJson(): Json = Json {
|
||
ignoreUnknownKeys = true
|
||
coerceInputValues = true
|
||
}
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideBaseOkHttpClient(): OkHttpClient = OkHttpClient.Builder()
|
||
.connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
|
||
.readTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
|
||
.apply {
|
||
// Логирование каждого HTTP-запроса — только в debug. В релизе это лишний
|
||
// оверхед на каждый вызов и утечка URL/деталей в logcat.
|
||
if (com.radiola.BuildConfig.DEBUG) {
|
||
addInterceptor(HttpLoggingInterceptor().apply {
|
||
level = HttpLoggingInterceptor.Level.BASIC
|
||
})
|
||
}
|
||
}
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
@Named("radiolaClient")
|
||
fun provideRadiolaOkHttpClient(
|
||
baseClient: OkHttpClient,
|
||
authInterceptor: AuthInterceptor
|
||
): OkHttpClient = baseClient.newBuilder()
|
||
.addInterceptor(authInterceptor)
|
||
// Распознавание Shazam на бэкенде асинхронное (тянет аудио из потока +
|
||
// поллит результат ~до 18с) — базового readTimeout 10с не хватает.
|
||
// Поднимаем таймаут точечно только для этого пути.
|
||
.addInterceptor { chain ->
|
||
val req = chain.request()
|
||
if (req.url.encodedPath.contains("shazam/recognize")) {
|
||
chain.withReadTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
|
||
.withConnectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
|
||
.proceed(req)
|
||
} else {
|
||
chain.proceed(req)
|
||
}
|
||
}
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
@Named("record")
|
||
fun provideRecordRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
|
||
.baseUrl("https://www.radiorecord.ru/")
|
||
.client(okHttpClient)
|
||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
@Named("radiola")
|
||
fun provideRadiolaRetrofit(
|
||
@Named("radiolaClient") okHttpClient: OkHttpClient,
|
||
json: Json
|
||
): Retrofit = Retrofit.Builder()
|
||
.baseUrl("http://121.127.37.212:3000/")
|
||
.client(okHttpClient)
|
||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
@Named("itunes")
|
||
fun provideItunesRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
|
||
.baseUrl("https://itunes.apple.com/")
|
||
.client(okHttpClient)
|
||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideItunesApi(@Named("itunes") retrofit: Retrofit): com.radiola.data.remote.ItunesApi =
|
||
retrofit.create(com.radiola.data.remote.ItunesApi::class.java)
|
||
|
||
@Provides
|
||
@Singleton
|
||
@Named("lrclib")
|
||
fun provideLrcLibRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
|
||
.baseUrl("https://lrclib.net/")
|
||
.client(okHttpClient)
|
||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
@Named("love")
|
||
fun provideLoveRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
|
||
.baseUrl("https://api.loveradio.ru/api/v1/love-radio/")
|
||
.client(okHttpClient)
|
||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideLoveApi(@Named("love") retrofit: Retrofit): LoveApi = retrofit.create(LoveApi::class.java)
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideLrcLibApi(@Named("lrclib") retrofit: Retrofit): LrcLibApi = retrofit.create(LrcLibApi::class.java)
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideRecordApi(@Named("record") retrofit: Retrofit): RecordApi = retrofit.create(RecordApi::class.java)
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideRadiolaApi(@Named("radiola") retrofit: Retrofit): RadiolaApi = retrofit.create(RadiolaApi::class.java)
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideDatabase(@ApplicationContext context: Context): AppDatabase =
|
||
Room.databaseBuilder(context, AppDatabase::class.java, "radiola.db")
|
||
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8)
|
||
.build()
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideAlarmDao(db: AppDatabase): AlarmDao = db.alarmDao()
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideStationDao(db: AppDatabase): com.radiola.data.local.dao.StationDao = db.stationDao()
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideLocalStationDataSource(
|
||
@ApplicationContext context: Context,
|
||
json: Json
|
||
): LocalStationDataSource = LocalStationDataSource(context, json)
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideStationRepository(impl: StationRepositoryImpl): StationRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideNowPlayingRepository(impl: NowPlayingRepositoryImpl): NowPlayingRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideFavoritesRepository(impl: FavoritesRepositoryImpl): FavoritesRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideTrackHistoryRepository(impl: TrackHistoryRepositoryImpl): TrackHistoryRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideSettingsRepository(impl: SettingsRepositoryImpl): SettingsRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideRegionRepository(impl: RegionRepositoryImpl): RegionRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideRecordingRepository(impl: RecordingRepositoryImpl): RecordingRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideAuthRepository(impl: AuthRepositoryImpl): AuthRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideSyncRepository(impl: SyncRepositoryImpl): SyncRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideChartsRepository(impl: ChartsRepositoryImpl): ChartsRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideLyricsRepository(impl: LyricsRepositoryImpl): LyricsRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideRecognizedTrackRepository(impl: RecognizedTrackRepositoryImpl): RecognizedTrackRepository = impl
|
||
|
||
@Provides
|
||
@Singleton
|
||
fun provideShazamRepository(impl: ShazamRepositoryImpl): ShazamRepository = impl
|
||
}
|