Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ interface SubscriptionsDao {
suspend fun getByUrl(url: String): Subscription?

@Query("SELECT * FROM subscriptions WHERE id=:id")
fun getWithCredentialsByIdFlow(id: Long): Flow<SubscriptionWithCredential?>
suspend fun getWithCredentialsById(id: Long): SubscriptionWithCredential?

@Query("SELECT errorMessage FROM subscriptions WHERE id=:id")
fun getErrorMessageFlow(id: Long): Flow<String?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch

@HiltViewModel(assistedFactory = EditSubscriptionModel.EditSubscriptionModelFactory::class)
Expand All @@ -42,7 +41,7 @@ class EditSubscriptionModel @AssistedInject constructor(

private var initialSubscription: Subscription? = null
private var initialCredential: Credential? = null
private var initialRequiresAuthValue: Boolean? = null
private val initialRequiresAuth: Boolean get() = initialCredential != null

/**
* Whether user input is error free
Expand All @@ -69,7 +68,7 @@ class EditSubscriptionModel @AssistedInject constructor(
get() = with(subscriptionSettingsUseCase) {
val requiresAuth = uiState.requiresAuth

val credentialsDirty = initialRequiresAuthValue != requiresAuth || initialCredential?.let {
val credentialsDirty = initialRequiresAuth != requiresAuth || initialCredential?.let {
!equalsCredential(it)
} ?: false
val subscriptionsDirty = initialSubscription?.let {
Expand All @@ -82,56 +81,38 @@ class EditSubscriptionModel @AssistedInject constructor(
var successMessage: String? by mutableStateOf(null)
private set

val subscription = db.subscriptionsDao().getByIdFlow(subscriptionId)
val subscriptionWithCredential = db.subscriptionsDao().getWithCredentialsByIdFlow(subscriptionId)
var subscriptionWithCredential: SubscriptionsDao.SubscriptionWithCredential? = null
private set

init {
// Initialise view models and save their initial state
viewModelScope.launch {
subscriptionWithCredential.collect { data ->
if (data != null)
onSubscriptionLoaded(data)
db.subscriptionsDao().getWithCredentialsById(subscriptionId)?.let {
onSubscriptionLoaded(it)
}
}
}

/**
* Initialise view models and remember their initial state
*/
private fun onSubscriptionLoaded(subscriptionWithCredential: SubscriptionsDao.SubscriptionWithCredential) =
with(subscriptionSettingsUseCase) {
val subscription = subscriptionWithCredential.subscription

setUrl(subscription.url.toString())
setTitle(subscription.displayName)
setColor(subscription.color)
setCustomUserAgent(subscription.customUserAgent)
setIgnoreAlerts(subscription.ignoreEmbeddedAlerts)
setDefaultAlarmMinutes(subscription.defaultAlarmMinutes?.toString())
setDefaultAllDayAlarmMinutes(subscription.defaultAllDayAlarmMinutes?.toString())
setIgnoreDescription(subscription.ignoreDescription)

val credential = subscriptionWithCredential.credential
val requiresAuth = credential != null
setRequiresAuth(requiresAuth)

if (credential != null) {
setUsername(credential.username)
setPassword(credential.password)
}
private fun onSubscriptionLoaded(subscriptionWithCredential: SubscriptionsDao.SubscriptionWithCredential) {
val subscription = subscriptionWithCredential.subscription
val credential = subscriptionWithCredential.credential

// Save state, before user makes changes
initialSubscription = subscription
initialCredential = credential
initialRequiresAuthValue = uiState.requiresAuth
}
// Save the initial state, before updating the UI, so the state is persisted
initialSubscription = subscription
initialCredential = credential
this.subscriptionWithCredential = subscriptionWithCredential

subscriptionSettingsUseCase.update(subscription, credential)
}

/**
* Updates the loaded subscription from the data provided by the view models.
*/
fun updateSubscription() = with(subscriptionSettingsUseCase.uiState) {
viewModelScope.launch(Dispatchers.IO) {
subscription.firstOrNull()?.let { subscription ->
subscriptionWithCredential?.let { (subscription) ->
val newSubscription = subscription.copy(
displayName = title ?: subscription.displayName,
color = color,
Expand Down Expand Up @@ -163,7 +144,7 @@ class EditSubscriptionModel @AssistedInject constructor(
*/
fun removeSubscription() {
viewModelScope.launch(Dispatchers.IO) {
subscription.firstOrNull()?.let { subscription ->
subscriptionWithCredential?.let { (subscription) ->
db.subscriptionsDao().delete(subscription)

// sync the subscription to reflect the changes in the calendar provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,23 @@ class SubscriptionSettingsUseCase @Inject constructor() {
uiState = uiState.copy(ignoreDescription = value)
}

fun update(subscription: Subscription, credential: Credential?) {
uiState = uiState.copy(
url = subscription.url.toString(),
title = subscription.displayName,
color = subscription.color,
customUserAgent = subscription.customUserAgent,
ignoreAlerts = subscription.ignoreEmbeddedAlerts,
defaultAlarmMinutes = subscription.defaultAlarmMinutes,
defaultAllDayAlarmMinutes = subscription.defaultAllDayAlarmMinutes,
ignoreDescription = subscription.ignoreDescription,

requiresAuth = credential != null,
username = credential?.username,
password = credential?.password
)
}

fun equalsSubscription(subscription: Subscription) =
uiState.url == subscription.url.toString()
&& uiState.title == subscription.displayName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import at.bitfire.icsdroid.R
import at.bitfire.icsdroid.db.entity.Subscription
import at.bitfire.icsdroid.model.EditSubscriptionModel
Expand All @@ -54,7 +53,7 @@ fun EditSubscriptionScreen(
val model = hiltViewModel<EditSubscriptionModel, EditSubscriptionModelFactory> { factory ->
factory.create(subscriptionId)
}
val subscription = model.subscription.collectAsStateWithLifecycle(null)

with(model.subscriptionSettingsUseCase) {
EditSubscriptionScreen(
inputValid = model.inputValid,
Expand All @@ -63,8 +62,8 @@ fun EditSubscriptionScreen(
onDelete = model::removeSubscription,
onSave = model::updateSubscription,
onShare = {
subscription.value?.let {
onShare(it)
model.subscriptionWithCredential?.let { (subscription) ->
onShare(subscription)
}
},
onExit = onExit,
Expand Down