Additional Performance Improvements

This commit is contained in:
Vitor Pamplona
2023-01-18 14:24:04 -05:00
parent 381711b72e
commit bf8a0f0e76
10 changed files with 46 additions and 25 deletions

View File

@@ -297,8 +297,6 @@ object LocalCache {
it.addReply(note) it.addReply(note)
} }
UrlCachedPreviewer.preloadPreviewsFor(note)
refreshObservers() refreshObservers()
} }

View File

@@ -8,6 +8,10 @@ import com.vitorpamplona.amethyst.ui.components.isValidURL
import com.vitorpamplona.amethyst.ui.components.noProtocolUrlValidator import com.vitorpamplona.amethyst.ui.components.noProtocolUrlValidator
import com.vitorpamplona.amethyst.ui.components.videoExtension import com.vitorpamplona.amethyst.ui.components.videoExtension
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object UrlCachedPreviewer { object UrlCachedPreviewer {
val cache = ConcurrentHashMap<String, UrlInfoItem>() val cache = ConcurrentHashMap<String, UrlInfoItem>()
@@ -18,16 +22,19 @@ object UrlCachedPreviewer {
return return
} }
BahaUrlPreview(url, object : IUrlPreviewCallback { val scope = CoroutineScope(Job() + Dispatchers.Main)
override fun onComplete(urlInfo: UrlInfoItem) { scope.launch {
cache.put(url, urlInfo) BahaUrlPreview(url, object : IUrlPreviewCallback {
callback?.onComplete(urlInfo) override fun onComplete(urlInfo: UrlInfoItem) {
} cache.put(url, urlInfo)
callback?.onComplete(urlInfo)
}
override fun onFailed(throwable: Throwable) { override fun onFailed(throwable: Throwable) {
callback?.onFailed(throwable) callback?.onFailed(throwable)
} }
}).fetchUrlPreview() }).fetchUrlPreview()
}
} }
fun findUrlsInMessage(message: String): List<String> { fun findUrlsInMessage(message: String): List<String> {

View File

@@ -137,13 +137,14 @@ class UserMetadata {
} }
class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) { class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
val scope = CoroutineScope(Job() + Dispatchers.Main)
fun refresh() { fun refresh() {
postValue(UserState(user)) postValue(UserState(user))
} }
override fun onActive() { override fun onActive() {
super.onActive() super.onActive()
val scope = CoroutineScope(Job() + Dispatchers.Main)
scope.launch { scope.launch {
NostrSingleUserDataSource.add(user.pubkeyHex) NostrSingleUserDataSource.add(user.pubkeyHex)
} }
@@ -151,7 +152,6 @@ class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
override fun onInactive() { override fun onInactive() {
super.onInactive() super.onInactive()
val scope = CoroutineScope(Job() + Dispatchers.Main)
scope.launch { scope.launch {
NostrSingleUserDataSource.remove(user.pubkeyHex) NostrSingleUserDataSource.remove(user.pubkeyHex)
} }

View File

@@ -1,5 +1,7 @@
package com.vitorpamplona.amethyst.service package com.vitorpamplona.amethyst.service
import android.os.Handler
import android.os.Looper
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.UrlCachedPreviewer import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
@@ -125,7 +127,7 @@ abstract class NostrDataSource<T>(val debugName: String) {
return returningList return returningList
} }
suspend fun loadPreviews(list: List<T>) { fun loadPreviews(list: List<T>) {
list.forEach { list.forEach {
if (it is Note) { if (it is Note) {
UrlCachedPreviewer.preloadPreviewsFor(it) UrlCachedPreviewer.preloadPreviewsFor(it)
@@ -146,6 +148,19 @@ abstract class NostrDataSource<T>(val debugName: String) {
channelIds.remove(channel.id) channelIds.remove(channel.id)
} }
val filterHandler = Handler(Looper.getMainLooper())
var handlerWaiting = false
@Synchronized
fun invalidateFilters() {
if (handlerWaiting) return
handlerWaiting = true
filterHandler.postDelayed({
resetFilters()
handlerWaiting = false
}, 200)
}
fun resetFilters() { fun resetFilters() {
// saves the channels that are currently active // saves the channels that are currently active
val activeChannels = channels.filter { it.filter != null } val activeChannels = channels.filter { it.filter != null }

View File

@@ -70,11 +70,11 @@ object NostrSingleEventDataSource: NostrDataSource<Note>("SingleEventFeed") {
fun add(eventId: String) { fun add(eventId: String) {
eventsToWatch = eventsToWatch.plus(eventId) eventsToWatch = eventsToWatch.plus(eventId)
resetFilters() invalidateFilters()
} }
fun remove(eventId: String) { fun remove(eventId: String) {
eventsToWatch = eventsToWatch.minus(eventId) eventsToWatch = eventsToWatch.minus(eventId)
resetFilters() invalidateFilters()
} }
} }

View File

@@ -35,11 +35,11 @@ object NostrSingleUserDataSource: NostrDataSource<Note>("SingleUserFeed") {
fun add(userId: String) { fun add(userId: String) {
usersToWatch = usersToWatch.plus(userId) usersToWatch = usersToWatch.plus(userId)
resetFilters() invalidateFilters()
} }
fun remove(userId: String) { fun remove(userId: String) {
usersToWatch = usersToWatch.minus(userId) usersToWatch = usersToWatch.minus(userId)
resetFilters() invalidateFilters()
} }
} }

View File

@@ -16,6 +16,7 @@ import coil.decode.ImageDecoderDecoder
import coil.decode.SvgDecoder import coil.decode.SvgDecoder
import com.vitorpamplona.amethyst.KeyStorage import com.vitorpamplona.amethyst.KeyStorage
import com.vitorpamplona.amethyst.service.NostrAccountDataSource import com.vitorpamplona.amethyst.service.NostrAccountDataSource
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
import com.vitorpamplona.amethyst.service.NostrGlobalDataSource import com.vitorpamplona.amethyst.service.NostrGlobalDataSource
import com.vitorpamplona.amethyst.service.NostrHomeDataSource import com.vitorpamplona.amethyst.service.NostrHomeDataSource
@@ -71,6 +72,7 @@ class MainActivity : ComponentActivity() {
override fun onPause() { override fun onPause() {
NostrAccountDataSource.stop() NostrAccountDataSource.stop()
NostrHomeDataSource.stop() NostrHomeDataSource.stop()
NostrChannelDataSource.stop()
NostrChatroomListDataSource.stop() NostrChatroomListDataSource.stop()
NostrUserProfileDataSource.stop() NostrUserProfileDataSource.stop()
NostrUserProfileFollowersDataSource.stop() NostrUserProfileFollowersDataSource.stop()

View File

@@ -6,6 +6,7 @@ import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.DefaultChannels import com.vitorpamplona.amethyst.model.DefaultChannels
import com.vitorpamplona.amethyst.model.toByteArray import com.vitorpamplona.amethyst.model.toByteArray
import com.vitorpamplona.amethyst.service.NostrAccountDataSource import com.vitorpamplona.amethyst.service.NostrAccountDataSource
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
import com.vitorpamplona.amethyst.service.NostrGlobalDataSource import com.vitorpamplona.amethyst.service.NostrGlobalDataSource
import com.vitorpamplona.amethyst.service.NostrHomeDataSource import com.vitorpamplona.amethyst.service.NostrHomeDataSource
@@ -70,6 +71,7 @@ class AccountStateViewModel(private val encryptedPreferences: EncryptedSharedPre
NostrNotificationDataSource.account = account NostrNotificationDataSource.account = account
NostrChatroomListDataSource.account = account NostrChatroomListDataSource.account = account
NostrChannelDataSource.start()
NostrAccountDataSource.start() NostrAccountDataSource.start()
NostrGlobalDataSource.start() NostrGlobalDataSource.start()
NostrHomeDataSource.start() NostrHomeDataSource.start()

View File

@@ -6,6 +6,9 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.LocalCacheState import com.vitorpamplona.amethyst.model.LocalCacheState
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.NostrDataSource import com.vitorpamplona.amethyst.service.NostrDataSource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@@ -18,13 +21,6 @@ class FeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
val feedContent = _feedContent.asStateFlow() val feedContent = _feedContent.asStateFlow()
fun refresh() { fun refresh() {
// For some reason, view Model Scope doesn't call
viewModelScope.launch {
refreshSuspend()
}
}
fun refreshSuspend() {
val notes = dataSource.loadTop() val notes = dataSource.loadTop()
val oldNotesState = feedContent.value val oldNotesState = feedContent.value

View File

@@ -17,6 +17,7 @@ import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.TextField import androidx.compose.material.TextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf