-
Notifications
You must be signed in to change notification settings - Fork 5
fix(accounts): retire private memory on removal #456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
07612a6
1d17fca
3e1b1bc
8fa04dc
96fffba
823d5d9
f2b768e
8dc723e
bc3ef02
c87c477
cf27a24
f42ea36
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| category: fix | ||
| issue: 172 | ||
| pull: none | ||
| platforms: android, desktop | ||
| user-facing: yes | ||
|
|
||
| Removing an account clears its previews, Notes cache, support drafts, and other private in-memory state. Memories timeline indices keep only four recently used account scopes. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,13 @@ package dev.obiente.nextcloudnative.app | |
|
|
||
| import androidx.compose.runtime.mutableStateOf | ||
|
|
||
| internal enum class StatusExpiryChoice(val label: String, val seconds: Long?) { | ||
| Never("No expiry", null), | ||
| OneHour("1 hour", 60L * 60L), | ||
| FourHours("4 hours", 4L * 60L * 60L), | ||
| OneDay("24 hours", 24L * 60L * 60L), | ||
| } | ||
|
|
||
| internal class PhotoTimelineUiState { | ||
| val timeline = mutableStateOf(PhotoTimelineState(pageSize = MAX_PHOTO_TIMELINE_PAGE_SIZE)) | ||
| val backupStatuses = mutableStateOf<Map<String, MediaBackupStatus>>(emptyMap()) | ||
|
|
@@ -10,22 +17,29 @@ internal class PhotoTimelineUiState { | |
|
|
||
| internal object PhotoTimelineUiStateRepository { | ||
| private const val MAXIMUM_ACCOUNT_STATES = 4 | ||
| private val gate = sharedAccountPrivateMemoryGate | ||
| private val accountStates = linkedMapOf<String, PhotoTimelineUiState>() | ||
|
|
||
| fun stateFor(session: NextcloudSession): PhotoTimelineUiState { | ||
| fun stateFor(session: NextcloudSession): PhotoTimelineUiState = gate.read( | ||
| session.accountId.storageKey, null, | ||
| ) { | ||
| val accountKey = previewCacheDigest(session) | ||
| accountStates.remove(accountKey)?.let { existing -> | ||
| accountStates[accountKey] = existing | ||
| return existing | ||
| return@read existing | ||
| } | ||
| val created = PhotoTimelineUiState() | ||
| accountStates[accountKey] = created | ||
| while (accountStates.size > MAXIMUM_ACCOUNT_STATES) accountStates.remove(accountStates.keys.first()) | ||
| return created | ||
| } | ||
| created | ||
| } ?: PhotoTimelineUiState() | ||
|
|
||
| fun removeAccount(accountStorageKey: String) { | ||
| accountStates.remove(accountStorageKey) | ||
| internal fun purgeRetiredAccount(accountStorageKey: String) { | ||
| accountStates.remove(accountStorageKey)?.let { retired -> | ||
| retired.timeline.value = PhotoTimelineState(pageSize = MAX_PHOTO_TIMELINE_PAGE_SIZE) | ||
| retired.backupStatuses.value = emptyMap() | ||
| retired.initialLoadCompleted.value = false | ||
|
Comment on lines
+38
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If an in-flight timeline load completes after account retirement but before the old AGENTS.md reference: AGENTS.md:L327-L328 Useful? React with 👍 / 👎. |
||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -40,6 +54,13 @@ internal sealed interface CalendarLoadState { | |
| data class Error(val message: String) : CalendarLoadState | ||
| } | ||
|
|
||
| internal fun calendarReadyMatchesRequest( | ||
| readyMonth: CalendarMonth, | ||
| readyWindow: GroupwareDavTimeWindow, | ||
| requestedMonth: CalendarMonth, | ||
| requestedWindow: GroupwareDavTimeWindow, | ||
| ): Boolean = readyMonth == requestedMonth && readyWindow == requestedWindow | ||
|
|
||
| internal object CalendarWorkspaceMemoryCache { | ||
| private val gate = sharedAccountPrivateMemoryGate | ||
| private val entries = linkedMapOf<Pair<NextcloudAccountId, String>, CalendarLoadState.Ready>() | ||
|
|
@@ -98,8 +119,7 @@ internal object UserStatusWorkspaceMemoryCache { | |
| private val gate = sharedAccountPrivateMemoryGate | ||
| private val entries = linkedMapOf<NextcloudAccountId, UserStatusSurfaceState.Available>() | ||
|
|
||
| fun producer(session: NextcloudSession): AccountPrivateMemoryProducer? = | ||
| gate.producer(session.accountId.storageKey) | ||
| fun producer(session: NextcloudSession): AccountPrivateMemoryProducer? = gate.producer(session.accountId.storageKey) | ||
|
|
||
| fun get(session: NextcloudSession): UserStatusSurfaceState.Available? = | ||
| gate.read(session.accountId.storageKey, null) { | ||
|
|
@@ -215,7 +235,7 @@ internal fun removeUserStatusWorkspaceMemory(accountStorageKey: String) = | |
| UserStatusWorkspaceMemoryCache.purgeRetiredAccount(accountStorageKey) | ||
|
|
||
| internal fun removeNextcloudNativeWorkspaceMemory(accountStorageKey: String) { | ||
| PhotoTimelineUiStateRepository.removeAccount(accountStorageKey) | ||
| PhotoTimelineUiStateRepository.purgeRetiredAccount(accountStorageKey) | ||
| ActivityWorkspaceMemoryCache.purgeRetiredAccount(accountStorageKey) | ||
| TalkWorkspaceMemoryCache.purgeRetiredAccount(accountStorageKey) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.