Browse Source

Cancel avatar transfers after their last Android viewer closes

master
evgeny 5 days ago
parent
commit
6bd6ea540c
  1. 16
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/AvatarRepository.kt

16
tools/chatgui-android/app/src/main/java/com/utun/chat/data/AvatarRepository.kt

@ -45,6 +45,7 @@ class AvatarRepository(context: Context) {
val edits: StateFlow<Map<String, AvatarEditState>> = _edits val edits: StateFlow<Map<String, AvatarEditState>> = _edits
private val loads = mutableSetOf<String>() private val loads = mutableSetOf<String>()
private val objectLoads = mutableMapOf<String, Deferred<Unit>>() private val objectLoads = mutableMapOf<String, Deferred<Unit>>()
private val objectWaiters = mutableMapOf<String,Int>()
private val memberRequests = mutableMapOf<String, Long>() private val memberRequests = mutableMapOf<String, Long>()
private val editTokens = mutableMapOf<String, Long>() private val editTokens = mutableMapOf<String, Long>()
private val replications = mutableSetOf<String>() private val replications = mutableSetOf<String>()
@ -163,7 +164,8 @@ class AvatarRepository(context: Context) {
if (p.type in 49..50 && NativeLib.isReady()) { p.cancelled = true; NativeLib.cancelAvatar(id) } if (p.type in 49..50 && NativeLib.isReady()) { p.cancelled = true; NativeLib.cancelAvatar(id) }
} }
scope.coroutineContext.cancelChildren() scope.coroutineContext.cancelChildren()
pending.clear(); loads.clear(); objectLoads.clear(); replications.clear(); dirtyGroups.clear(); memberRequests.clear(); editTokens.clear() pending.clear(); loads.clear(); objectLoads.clear(); objectWaiters.clear()
replications.clear(); dirtyGroups.clear(); memberRequests.clear(); editTokens.clear()
account = 0; defaultAvatar = null; cache.evictAll() account = 0; defaultAvatar = null; cache.evictAll()
_members.value = emptyMap(); _groups.value = emptyMap(); _edits.value = emptyMap(); changed() _members.value = emptyMap(); _groups.value = emptyMap(); _edits.value = emptyMap(); changed()
} }
@ -325,8 +327,18 @@ class AvatarRepository(context: Context) {
alive(epoch); log("DEBUG", "Object ready file=$file cache=$hit group=$group") alive(epoch); log("DEBUG", "Object ready file=$file cache=$hit group=$group")
} }
}.also { objectLoads[file]=it } }.also { objectLoads[file]=it }
objectWaiters[file]=(objectWaiters[file] ?: 0)+1
try { operation.await(); alive(epoch) } try { operation.await(); alive(epoch) }
finally { if (generation==epoch && operation.isCompleted && objectLoads[file]===operation) objectLoads.remove(file) } finally {
if (generation==epoch) {
val remaining=(objectWaiters[file] ?: 1)-1
if (remaining==0) {
objectWaiters.remove(file)
if (objectLoads[file]===operation) objectLoads.remove(file)
if (!operation.isCompleted) { log("DEBUG", "Cancel unused object=$file"); operation.cancel() }
} else objectWaiters[file]=remaining
}
}
} }
suspend fun loadAvatar(group: String, m: ChatMember, original: Boolean): Bitmap { suspend fun loadAvatar(group: String, m: ChatMember, original: Boolean): Bitmap {

Loading…
Cancel
Save