Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3bdd646
fix(android): preserve account-owned background uploads
veryCrunchy Sep 1, 2026
a770194
chore(changelog): link account background upload fix
veryCrunchy Sep 1, 2026
1843de9
docs(platform): bind uploads to supplied sessions
veryCrunchy Sep 4, 2026
2f7800b
refactor(platform): keep upload contract compact
veryCrunchy Sep 4, 2026
3de794e
fix(android): honor durable upload account lease
veryCrunchy Sep 4, 2026
f63bda7
refactor(android): own durable upload execution
veryCrunchy Sep 4, 2026
d400a48
fix(uploads): recover worker account metadata
veryCrunchy Sep 4, 2026
5cfe4d8
fix(uploads): defer ambiguous account recovery
veryCrunchy Sep 4, 2026
47a915e
fix(uploads): retire removed account work
veryCrunchy Sep 5, 2026
41ade6c
refactor(accounts): keep registry adapter bounded
veryCrunchy Sep 5, 2026
7b9e6cc
chore(website): refresh marketing captures
obiente-automations[bot] Sep 5, 2026
d5c6611
refactor(accounts): keep Android services bounded
veryCrunchy Sep 5, 2026
c7a93dc
refactor(android): keep upload resolution bounded
veryCrunchy Sep 5, 2026
b04f8b6
fix(uploads): contain corrupt registry preference
veryCrunchy Sep 5, 2026
93752cf
fix(uploads): retry corrupt registry preference
veryCrunchy Sep 5, 2026
54386f6
refactor(platform): keep recovery contract bounded
veryCrunchy Sep 5, 2026
7367e96
fix(accounts): preserve background recovery state
veryCrunchy Sep 6, 2026
d815af9
chore(website): refresh marketing captures
obiente-automations[bot] Sep 6, 2026
58ee098
chore(website): refresh marketing captures
obiente-automations[bot] Sep 6, 2026
147e3c4
fix(platform): honor the source size ceiling
veryCrunchy Sep 6, 2026
bfcfd0f
fix(uploads): quarantine unreadable queues
veryCrunchy Sep 6, 2026
3f6a01a
fix(uploads): stop retrying malformed registries
veryCrunchy Sep 6, 2026
8d1c884
Merge branch 'feature/account-credential-slots' into fix/account-back…
veryCrunchy Sep 9, 2026
435dab3
chore(website): refresh marketing captures
obiente-automations[bot] Sep 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ internal class AndroidAccountCredentialController(
},
)

fun accountRetentionSnapshot(): AndroidAccountRetentionSnapshot = readRegistryForCredentialLoad()
?.let { registry -> AndroidAccountRetentionSnapshot.Available(registry.accounts, registry.activeAccountId) }
?: AndroidAccountRetentionSnapshot.Unavailable
fun accountRetentionSnapshot(): AndroidAccountRetentionSnapshot =
readRegistryForCredentialLoad().asAccountRetentionSnapshot()

fun durableUploadAccountRegistry(): DurableUploadAccountRegistry = readCredentialFreeRegistry().asDurableRegistry()
fun activeAccountId(): NextcloudAccountId? = readCredentialFreeRegistry()?.activeAccountId
fun loadSession(accountId: NextcloudAccountId): NextcloudSession? =
ANDROID_ACCOUNT_CREDENTIAL_STORE_GUARD.serialize {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ internal fun resolveStoredAndroidAccountSession(

internal const val ANDROID_ACCOUNT_SESSION_KEY = "encrypted_session"
internal const val ANDROID_ACCOUNT_REGISTRY_KEY = "account_registry_v1"
internal const val ANDROID_ACCOUNT_PREFERENCES_NAME = "nextcloud_native"
internal const val ANDROID_ACCOUNT_CREDENTIAL_SLOT_KEY_PREFIX = "account_credential_v1:"
internal const val ANDROID_QUARANTINED_SESSION_KEY = "encrypted_session_quarantine"
internal const val ANDROID_PENDING_ACCOUNT_REMOVAL_CLEANUP_KEY = "pending_account_removal_cleanup_v2"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.obiente.nextcloudnative

import android.content.SharedPreferences
import dev.obiente.nextcloudnative.app.NextcloudAccountRegistry
import dev.obiente.nextcloudnative.app.NextcloudSession
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.NonCancellable
Expand Down Expand Up @@ -27,6 +29,37 @@ internal suspend fun replaceAndroidActiveStateWithAccountLeases(
}
}

internal fun NextcloudAccountRegistry?.asDurableRegistry(): DurableUploadAccountRegistry =
this?.let { registry ->
DurableUploadAccountRegistry.Available(
accounts = registry.accounts,
activeAccountId = registry.activeAccountId,
)
}
?: DurableUploadAccountRegistry.Unavailable

internal fun NextcloudAccountRegistry?.asAccountRetentionSnapshot(): AndroidAccountRetentionSnapshot =
this?.let { registry ->
AndroidAccountRetentionSnapshot.Available(
accounts = registry.accounts,
activeAccountId = registry.activeAccountId,
)
}
?: AndroidAccountRetentionSnapshot.Unavailable

internal fun SharedPreferences.durableUploadAccountResolutionAvailable(): Boolean =
durableUploadAccountResolutionAvailable {
getString(ANDROID_ACCOUNT_REGISTRY_KEY, null)
}

internal fun durableUploadAccountResolutionAvailable(
readRegistry: () -> String?,
): Boolean = try {
androidCredentialFreeRegistryAllowsAccountResolution(readRegistry())
} catch (_: ClassCastException) {
false
}

internal suspend fun rollbackUnavailableAndroidAccountRemoval(
active: Boolean = false,
recovered: AndroidAccountCredentialState,
Expand Down
Loading