Добавлен Yandex
This commit is contained in:
@@ -67,6 +67,8 @@ dependencies {
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.ui)
|
||||
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
@@ -9,30 +9,37 @@ import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.github.nullptroma.wallenc.app.auth.YandexSignInService
|
||||
import com.github.nullptroma.wallenc.presentation.WallencUi
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var yandexSignInService: YandexSignInService
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
yandexSignInService.registerWith(this)
|
||||
enableEdgeToEdge()
|
||||
requestNotificationPermissionIfNeeded()
|
||||
|
||||
Timber.plant(Timber.DebugTree())
|
||||
// val sdk = YandexAuthSdk.create(YandexAuthOptions(applicationContext, true))
|
||||
// val launcher =
|
||||
// registerForActivityResult(sdk.contract) { result -> handleResult(result) }
|
||||
// val loginOptions = YandexAuthLoginOptions(LoginType.CHROME_TAB)
|
||||
|
||||
setContent {
|
||||
WallencUi()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
yandexSignInService.unregister(this)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun requestNotificationPermissionIfNeeded() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
|
||||
val granted = ContextCompat.checkSelfPermission(
|
||||
@@ -50,12 +57,4 @@ class MainActivity : ComponentActivity() {
|
||||
companion object {
|
||||
private const val NOTIFICATION_PERMISSION_REQUEST_CODE = 100
|
||||
}
|
||||
|
||||
// private fun handleResult(result: YandexAuthResult) {
|
||||
// when (result) {
|
||||
// is YandexAuthResult.Success -> Toast.makeText(applicationContext, "Success: ${result.token}", Toast.LENGTH_SHORT).show()
|
||||
// is YandexAuthResult.Failure -> Toast.makeText(applicationContext, "Success: ${result.exception}", Toast.LENGTH_SHORT).show()
|
||||
// YandexAuthResult.Cancelled -> Toast.makeText(applicationContext, "Cancel", Toast.LENGTH_SHORT).show()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.github.nullptroma.wallenc.app.auth
|
||||
|
||||
import android.content.Context
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import com.github.nullptroma.wallenc.domain.auth.RemoteYandexAuthResult
|
||||
import com.github.nullptroma.wallenc.domain.auth.RemoteYandexSignInLauncher
|
||||
import com.yandex.authsdk.YandexAuthLoginOptions
|
||||
import com.yandex.authsdk.YandexAuthOptions
|
||||
import com.yandex.authsdk.YandexAuthResult
|
||||
import com.yandex.authsdk.YandexAuthSdk
|
||||
import com.yandex.authsdk.internal.strategy.LoginType
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Императивный вход через Yandex Auth SDK: [registerWith] в [ComponentActivity.onCreate],
|
||||
* [unregister] в [ComponentActivity.onDestroy], чтобы синглтон не держал [ActivityResultLauncher]
|
||||
* дольше жизни Activity.
|
||||
*
|
||||
* При смене конфигурации новая Activity может вызвать [registerWith] до [unregister] старой —
|
||||
* тогда владелец и launcher обновляются; [unregister] для уже неактуального экземпляра — no-op.
|
||||
*/
|
||||
@Singleton
|
||||
class YandexSignInService @Inject constructor(
|
||||
@ApplicationContext appContext: Context,
|
||||
) : RemoteYandexSignInLauncher {
|
||||
|
||||
private val sdk = YandexAuthSdk.create(YandexAuthOptions(appContext, true))
|
||||
|
||||
private var launcher: ActivityResultLauncher<YandexAuthLoginOptions>? = null
|
||||
|
||||
private var registrationOwner: ComponentActivity? = null
|
||||
|
||||
@Volatile
|
||||
private var pending: ((RemoteYandexAuthResult) -> Unit)? = null
|
||||
|
||||
fun registerWith(activity: ComponentActivity) {
|
||||
if (registrationOwner === activity && launcher != null) return
|
||||
launcher = activity.registerForActivityResult(sdk.contract) { result ->
|
||||
val mapped = mapYandexResult(result)
|
||||
val cb = synchronized(this) {
|
||||
val p = pending
|
||||
pending = null
|
||||
p
|
||||
}
|
||||
cb?.invoke(mapped)
|
||||
}
|
||||
registrationOwner = activity
|
||||
}
|
||||
|
||||
fun unregister(activity: ComponentActivity) {
|
||||
if (registrationOwner !== activity) return
|
||||
launcher = null
|
||||
registrationOwner = null
|
||||
val cb = synchronized(this) {
|
||||
val p = pending
|
||||
pending = null
|
||||
p
|
||||
}
|
||||
cb?.invoke(RemoteYandexAuthResult.Cancelled)
|
||||
}
|
||||
|
||||
override fun launch(onResult: (RemoteYandexAuthResult) -> Unit) {
|
||||
val l = launcher
|
||||
?: error("YandexSignInService: call registerWith(activity) from MainActivity.onCreate first")
|
||||
synchronized(this) {
|
||||
pending = onResult
|
||||
}
|
||||
l.launch(YandexAuthLoginOptions(LoginType.WEBVIEW))
|
||||
}
|
||||
|
||||
private fun mapYandexResult(result: YandexAuthResult): RemoteYandexAuthResult = when (result) {
|
||||
is YandexAuthResult.Success ->
|
||||
RemoteYandexAuthResult.Success(result.token.value)
|
||||
is YandexAuthResult.Failure ->
|
||||
RemoteYandexAuthResult.Failure(
|
||||
result.exception.message ?: result.exception.toString(),
|
||||
)
|
||||
YandexAuthResult.Cancelled -> RemoteYandexAuthResult.Cancelled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.github.nullptroma.wallenc.app.di.modules.auth
|
||||
|
||||
import com.github.nullptroma.wallenc.app.auth.YandexSignInService
|
||||
import com.github.nullptroma.wallenc.domain.auth.RemoteYandexSignInLauncher
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
abstract class YandexAuthModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract fun bindRemoteYandexSignInLauncher(
|
||||
impl: YandexSignInService,
|
||||
): RemoteYandexSignInLauncher
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.github.nullptroma.wallenc.data.db.RoomFactory
|
||||
import com.github.nullptroma.wallenc.data.db.app.IAppDb
|
||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
|
||||
import com.github.nullptroma.wallenc.data.db.app.dao.YandexAccountDao
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
@@ -32,6 +33,12 @@ class RoomModule {
|
||||
return database.storageMetaInfoDao
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYandexAccountDao(database: IAppDb): YandexAccountDao {
|
||||
return database.yandexAccountDao
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAppDb(
|
||||
|
||||
@@ -4,6 +4,9 @@ import android.content.Context
|
||||
import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher
|
||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
|
||||
import com.github.nullptroma.wallenc.data.db.app.dao.YandexAccountDao
|
||||
import com.github.nullptroma.wallenc.data.network.YandexUserInfoApi
|
||||
import com.github.nullptroma.wallenc.data.network.YandexUserInfoApiFactory
|
||||
import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository
|
||||
import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepository
|
||||
import com.github.nullptroma.wallenc.data.tasks.TaskOrchestrator
|
||||
@@ -28,14 +31,20 @@ class SingletonModule {
|
||||
@IoDispatcher ioDispatcher: CoroutineDispatcher,
|
||||
): ITaskOrchestrator = TaskOrchestrator(ioDispatcher)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYandexUserInfoApi(): YandexUserInfoApi = YandexUserInfoApiFactory.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideVaultsManager(
|
||||
@IoDispatcher ioDispatcher: CoroutineDispatcher,
|
||||
@ApplicationContext context: Context,
|
||||
keyRepo: StorageKeyMapRepository,
|
||||
yandexAccountDao: YandexAccountDao,
|
||||
yandexUserInfoApi: YandexUserInfoApi,
|
||||
): IVaultsManager {
|
||||
return VaultsManager(ioDispatcher, context, keyRepo)
|
||||
return VaultsManager(ioDispatcher, context, keyRepo, yandexAccountDao, yandexUserInfoApi)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
Reference in New Issue
Block a user