Skip to content

Commit

Permalink
split settings in sections and check if shared links is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed May 1, 2024
1 parent 17c78f3 commit 148974b
Show file tree
Hide file tree
Showing 14 changed files with 637 additions and 239 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.arkivanov.essenty.lifecycle.Lifecycle
import com.arkivanov.essenty.lifecycle.LifecycleOwner
import com.arkivanov.essenty.lifecycle.essentyLifecycle
import com.arkivanov.essenty.statekeeper.stateKeeper
import dev.datlag.aniflow.other.DomainVerifier
import dev.datlag.aniflow.other.UserHelper
import dev.datlag.aniflow.ui.navigation.RootComponent
import dev.datlag.tooling.compose.launchIO
Expand Down Expand Up @@ -52,6 +53,8 @@ class MainActivity : AppCompatActivity() {
di = di
)

DomainVerifier.verify(this)

setContent {
CompositionLocalProvider(
LocalLifecycleOwner provides lifecycleOwner,
Expand Down Expand Up @@ -88,6 +91,42 @@ class MainActivity : AppCompatActivity() {
)
}

override fun onDestroy() {
super.onDestroy()

DomainVerifier.verify(this)
}

override fun onStart() {
super.onStart()

DomainVerifier.verify(this)
}

override fun onResume() {
super.onResume()

DomainVerifier.verify(this)
}

override fun onPause() {
super.onPause()

DomainVerifier.verify(this)
}

override fun onStop() {
super.onStop()

DomainVerifier.verify(this)
}

override fun onRestart() {
super.onRestart()

DomainVerifier.verify(this)
}

private fun Uri.getFragmentOrQueryParameter(param: String): String? {
return this.fragment.getFragmentParameter(param) ?: getQueryParameter(param)?.ifBlank { null }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dev.datlag.aniflow.other

import android.content.Context
import android.content.Intent
import android.content.pm.verify.domain.DomainVerificationManager
import android.content.pm.verify.domain.DomainVerificationUserState
import android.net.Uri
import android.os.Build
import android.provider.Settings
import androidx.annotation.ChecksSdkIntAtLeast
import androidx.core.content.ContextCompat
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update

data object DomainVerifier {

@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S)
val supported: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
val verified: MutableStateFlow<Boolean> = MutableStateFlow(false)

@Suppress("NewApi")
fun verify(context: Context) {
if (supported) {
val manager = ContextCompat.getSystemService(context, DomainVerificationManager::class.java)
val userState = manager?.getDomainVerificationUserState(context.packageName)
val unapprovedDomains = userState?.hostToStateMap?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_NONE }

unapprovedDomains?.let { count ->
verified.update { count.isEmpty() }
}
}
}

@Suppress("NewApi")
fun enable(context: Context) {
if (supported) {
val intent = Intent(
Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
Uri.parse("package:${context.packageName}")
)
ContextCompat.startActivity(context, intent, null)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package dev.datlag.aniflow.ui.navigation.screen.initial.settings.component

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.Icon
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import dev.datlag.aniflow.other.DomainVerifier
import dev.datlag.tooling.decompose.lifecycle.collectAsStateWithLifecycle

@Composable
actual fun DomainSection(modifier: Modifier) {
if (DomainVerifier.supported) {
val context = LocalContext.current
val verified by DomainVerifier.verified.collectAsStateWithLifecycle()

SideEffect {
DomainVerifier.verify(context)
}

Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Icon(
imageVector = Icons.Filled.Share,
contentDescription = null,
)
Text(
text = "Open Links"
)
Spacer(modifier = Modifier.weight(1F))
Switch(
checked = verified,
onCheckedChange = {
DomainVerifier.enable(context)
},
enabled = !verified,
thumbContent = {
if (verified) {
Icon(
modifier = Modifier.size(SwitchDefaults.IconSize),
imageVector = Icons.Default.Check,
contentDescription = null
)
}
}
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import dev.datlag.aniflow.anilist.ViewerQuery
import dev.datlag.aniflow.anilist.model.User
import dev.datlag.aniflow.common.toMutation
import dev.datlag.aniflow.common.toSettings
import dev.datlag.aniflow.model.emitNotNull
import dev.datlag.aniflow.model.mutableStateIn
import dev.datlag.aniflow.model.safeFirstOrNull
import dev.datlag.aniflow.settings.Settings
import dev.datlag.tooling.async.suspendCatching
import dev.datlag.tooling.compose.ioDispatcher
import dev.datlag.tooling.compose.withIOContext
import dev.datlag.tooling.compose.withMainContext
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
import kotlinx.datetime.Clock
Expand All @@ -36,30 +40,23 @@ class UserHelper(
val isLoggedIn: Flow<Boolean> = userSettings.isAniListLoggedIn.distinctUntilChanged()
val loginUrl: String = "https://anilist.co/api/v2/oauth/authorize?client_id=$clientId&response_type=token"

private val changedUser: MutableStateFlow<User?> = MutableStateFlow(null)
private val userQuery = client.query(
ViewerQuery()
).toFlow().flowOn(ioDispatcher())
private val defaultUser = isLoggedIn.transform { loggedIn ->
@OptIn(DelicateCoroutinesApi::class)
private val updatableUser = isLoggedIn.transform { loggedIn ->
if (loggedIn) {
emitAll(
userQuery.map {
client.query(ViewerQuery()).toFlow().map {
it.data?.Viewer?.let(::User)
}
)
} else {
emit(null)
}
}.flowOn(ioDispatcher())
private val latestUser = defaultUser.transform { default ->
emit(default)
emitAll(changedUser.filterNotNull().map { changed ->
changedUser.update { null }
changed
})
}.flowOn(ioDispatcher())
}.mutableStateIn(
scope = GlobalScope,
initialValue = null
)

val user = latestUser.transform { user ->
val user = updatableUser.transform { user ->
emit(
user?.also {
appSettings.setData(
Expand All @@ -74,7 +71,7 @@ class UserHelper(

suspend fun updateAdultSetting(value: Boolean) {
appSettings.setAdultContent(value)
changedUser.emit(
updatableUser.emitNotNull(
client.mutation(
ViewerMutation(
adult = Optional.present(value)
Expand All @@ -87,7 +84,7 @@ class UserHelper(
appSettings.setColor(value)

if (value != null) {
changedUser.emit(
updatableUser.emitNotNull(
client.mutation(
ViewerMutation(
color = Optional.present(value.label)
Expand All @@ -101,7 +98,7 @@ class UserHelper(
appSettings.setTitleLanguage(value)

if (value != null) {
changedUser.emit(
updatableUser.emitNotNull(
client.mutation(
ViewerMutation(
title = Optional.presentIfNotNull(value.toMutation())
Expand All @@ -115,7 +112,7 @@ class UserHelper(
appSettings.setCharLanguage(value)

if (value != null) {
changedUser.emit(
updatableUser.emitNotNull(
client.mutation(
ViewerMutation(
char = Optional.presentIfNotNull(value.toMutation())
Expand Down
Loading

0 comments on commit 148974b

Please sign in to comment.