From bf8a0f0e7624510d86a70b69898938442e0252ad Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 18 Jan 2023 14:24:04 -0500 Subject: [PATCH] Additional Performance Improvements --- .../amethyst/model/LocalCache.kt | 2 -- .../amethyst/model/UrlCachedPreviewer.kt | 25 ++++++++++++------- .../com/vitorpamplona/amethyst/model/User.kt | 4 +-- .../amethyst/service/NostrDataSource.kt | 17 ++++++++++++- .../service/NostrSingleEventDataSource.kt | 4 +-- .../service/NostrSingleUserDataSource.kt | 4 +-- .../vitorpamplona/amethyst/ui/MainActivity.kt | 2 ++ .../ui/screen/AccountStateViewModel.kt | 2 ++ .../amethyst/ui/screen/FeedViewModel.kt | 10 +++----- .../ui/screen/loggedIn/ChannelScreen.kt | 1 + 10 files changed, 46 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index c9792eddb..ced9cccc2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -297,8 +297,6 @@ object LocalCache { it.addReply(note) } - UrlCachedPreviewer.preloadPreviewsFor(note) - refreshObservers() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/UrlCachedPreviewer.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/UrlCachedPreviewer.kt index 718103ba8..fe529c746 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/UrlCachedPreviewer.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/UrlCachedPreviewer.kt @@ -8,6 +8,10 @@ import com.vitorpamplona.amethyst.ui.components.isValidURL import com.vitorpamplona.amethyst.ui.components.noProtocolUrlValidator import com.vitorpamplona.amethyst.ui.components.videoExtension import java.util.concurrent.ConcurrentHashMap +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch object UrlCachedPreviewer { val cache = ConcurrentHashMap() @@ -18,16 +22,19 @@ object UrlCachedPreviewer { return } - BahaUrlPreview(url, object : IUrlPreviewCallback { - override fun onComplete(urlInfo: UrlInfoItem) { - cache.put(url, urlInfo) - callback?.onComplete(urlInfo) - } + val scope = CoroutineScope(Job() + Dispatchers.Main) + scope.launch { + BahaUrlPreview(url, object : IUrlPreviewCallback { + override fun onComplete(urlInfo: UrlInfoItem) { + cache.put(url, urlInfo) + callback?.onComplete(urlInfo) + } - override fun onFailed(throwable: Throwable) { - callback?.onFailed(throwable) - } - }).fetchUrlPreview() + override fun onFailed(throwable: Throwable) { + callback?.onFailed(throwable) + } + }).fetchUrlPreview() + } } fun findUrlsInMessage(message: String): List { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt index 5ab332b8d..e02c934a0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt @@ -137,13 +137,14 @@ class UserMetadata { } class UserLiveData(val user: User): LiveData(UserState(user)) { + val scope = CoroutineScope(Job() + Dispatchers.Main) + fun refresh() { postValue(UserState(user)) } override fun onActive() { super.onActive() - val scope = CoroutineScope(Job() + Dispatchers.Main) scope.launch { NostrSingleUserDataSource.add(user.pubkeyHex) } @@ -151,7 +152,6 @@ class UserLiveData(val user: User): LiveData(UserState(user)) { override fun onInactive() { super.onInactive() - val scope = CoroutineScope(Job() + Dispatchers.Main) scope.launch { NostrSingleUserDataSource.remove(user.pubkeyHex) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt index 2a736dea5..3ae4f5a2e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt @@ -1,5 +1,7 @@ package com.vitorpamplona.amethyst.service +import android.os.Handler +import android.os.Looper import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.UrlCachedPreviewer @@ -125,7 +127,7 @@ abstract class NostrDataSource(val debugName: String) { return returningList } - suspend fun loadPreviews(list: List) { + fun loadPreviews(list: List) { list.forEach { if (it is Note) { UrlCachedPreviewer.preloadPreviewsFor(it) @@ -146,6 +148,19 @@ abstract class NostrDataSource(val debugName: String) { 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() { // saves the channels that are currently active val activeChannels = channels.filter { it.filter != null } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt index 0eb4d44fc..8875eec79 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt @@ -70,11 +70,11 @@ object NostrSingleEventDataSource: NostrDataSource("SingleEventFeed") { fun add(eventId: String) { eventsToWatch = eventsToWatch.plus(eventId) - resetFilters() + invalidateFilters() } fun remove(eventId: String) { eventsToWatch = eventsToWatch.minus(eventId) - resetFilters() + invalidateFilters() } } \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt index b213c8ca7..781bb5910 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt @@ -35,11 +35,11 @@ object NostrSingleUserDataSource: NostrDataSource("SingleUserFeed") { fun add(userId: String) { usersToWatch = usersToWatch.plus(userId) - resetFilters() + invalidateFilters() } fun remove(userId: String) { usersToWatch = usersToWatch.minus(userId) - resetFilters() + invalidateFilters() } } \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index e6e58c618..d76c4d069 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -16,6 +16,7 @@ import coil.decode.ImageDecoderDecoder import coil.decode.SvgDecoder import com.vitorpamplona.amethyst.KeyStorage import com.vitorpamplona.amethyst.service.NostrAccountDataSource +import com.vitorpamplona.amethyst.service.NostrChannelDataSource import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource import com.vitorpamplona.amethyst.service.NostrGlobalDataSource import com.vitorpamplona.amethyst.service.NostrHomeDataSource @@ -71,6 +72,7 @@ class MainActivity : ComponentActivity() { override fun onPause() { NostrAccountDataSource.stop() NostrHomeDataSource.stop() + NostrChannelDataSource.stop() NostrChatroomListDataSource.stop() NostrUserProfileDataSource.stop() NostrUserProfileFollowersDataSource.stop() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt index 80d4d75c9..63c5b334b 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt @@ -6,6 +6,7 @@ import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.DefaultChannels import com.vitorpamplona.amethyst.model.toByteArray import com.vitorpamplona.amethyst.service.NostrAccountDataSource +import com.vitorpamplona.amethyst.service.NostrChannelDataSource import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource import com.vitorpamplona.amethyst.service.NostrGlobalDataSource import com.vitorpamplona.amethyst.service.NostrHomeDataSource @@ -70,6 +71,7 @@ class AccountStateViewModel(private val encryptedPreferences: EncryptedSharedPre NostrNotificationDataSource.account = account NostrChatroomListDataSource.account = account + NostrChannelDataSource.start() NostrAccountDataSource.start() NostrGlobalDataSource.start() NostrHomeDataSource.start() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt index c8aff13d6..53cb3aa44 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt @@ -6,6 +6,9 @@ import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCacheState import com.vitorpamplona.amethyst.model.Note 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.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -18,13 +21,6 @@ class FeedViewModel(val dataSource: NostrDataSource): ViewModel() { val feedContent = _feedContent.asStateFlow() fun refresh() { - // For some reason, view Model Scope doesn't call - viewModelScope.launch { - refreshSuspend() - } - } - - fun refreshSuspend() { val notes = dataSource.loadTop() val oldNotesState = feedContent.value diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt index 124dd2c25..be049c353 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.material.OutlinedTextField import androidx.compose.material.Text import androidx.compose.material.TextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf