Skip to content

Commit

Permalink
Improve caching and updating user account;
Browse files Browse the repository at this point in the history
Improve follow/unfollow business logic;
Improve local relays management;
Implement MissingRelaysException;
Show missing relays configuration error message;
Show follow/unfollow error messages;
  • Loading branch information
AleksandarIlic committed Aug 23, 2023
1 parent 8d83617 commit 7de6813
Show file tree
Hide file tree
Showing 33 changed files with 168 additions and 330 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class AuthRepository @Inject constructor(

suspend fun login(nostrKey: String): String {
val pubkey = credentialsStore.save(nostrKey)
userRepository.fetchAndUpsertUserAccount(userId = pubkey)
userRepository.createNewUserAccount(userId = pubkey)
userRepository.fetchAndUpdateUserAccount(userId = pubkey)
activeAccountStore.setActiveUserId(pubkey)
return pubkey
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface FeedContract {
data class FailedToPublishZapEvent(val cause: Throwable) : FeedError()
data class FailedToPublishRepostEvent(val cause: Throwable) : FeedError()
data class FailedToPublishLikeEvent(val cause: Throwable) : FeedError()
data class MissingRelaysConfiguration(val cause: Throwable) : FeedError()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
Expand Down Expand Up @@ -250,6 +249,7 @@ private fun ErrorHandler(
is FeedError.FailedToPublishZapEvent -> context.getString(R.string.post_action_zap_failed)
is FeedError.FailedToPublishLikeEvent -> context.getString(R.string.post_action_like_failed)
is FeedError.FailedToPublishRepostEvent -> context.getString(R.string.post_action_repost_failed)
is FeedError.MissingRelaysConfiguration -> context.getString(R.string.app_missing_relays_config)
else -> null
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import net.primal.android.discuss.feed.FeedContract.UiState.FeedError
import net.primal.android.feed.repository.FeedRepository
import net.primal.android.feed.repository.PostRepository
import net.primal.android.navigation.feedDirective
import net.primal.android.networking.relays.errors.MissingRelaysException
import net.primal.android.networking.relays.errors.NostrPublishException
import net.primal.android.user.accounts.active.ActiveAccountStore
import net.primal.android.user.accounts.active.ActiveUserAccountState
Expand Down Expand Up @@ -159,6 +160,8 @@ class FeedViewModel @Inject constructor(
)
} catch (error: NostrPublishException) {
setErrorState(error = FeedError.FailedToPublishLikeEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = FeedError.MissingRelaysConfiguration(error))
}
}

Expand All @@ -171,6 +174,8 @@ class FeedViewModel @Inject constructor(
)
} catch (error: NostrPublishException) {
setErrorState(error = FeedError.FailedToPublishRepostEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = FeedError.MissingRelaysConfiguration(error))
}
}

Expand All @@ -195,6 +200,8 @@ class FeedViewModel @Inject constructor(
setErrorState(error = FeedError.FailedToPublishZapEvent(error))
} catch (error: NostrPublishException) {
setErrorState(error = FeedError.FailedToPublishZapEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = FeedError.MissingRelaysConfiguration(error))
} catch (error: ZapRepository.InvalidZapRequestException) {
setErrorState(error = FeedError.InvalidZapRequest(error))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ interface NewPostContract {
data class UiState(
val preFillContent: String? = null,
val publishing: Boolean = false,
val error: PublishError? = null,
val error: NewPostError? = null,
val activeAccountAvatarUrl: String? = null,
) {
data class PublishError(val cause: Throwable?)
sealed class NewPostError {
data class PublishError(val cause: Throwable?) : NewPostError()
data class MissingRelaysConfiguration(val cause: Throwable) : NewPostError()
}

}

sealed class UiEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import net.primal.android.R
import net.primal.android.core.compose.AvatarThumbnailListItemImage
import net.primal.android.core.compose.button.PrimalLoadingButton
import net.primal.android.core.compose.PrimalTopAppBar
import net.primal.android.core.compose.button.PrimalLoadingButton
import net.primal.android.discuss.post.NewPostContract.UiState.NewPostError
import net.primal.android.theme.AppTheme

@Composable
Expand Down Expand Up @@ -161,14 +162,20 @@ fun NewPostScreen(

@Composable
private fun NewPostPublishErrorHandler(
error: NewPostContract.UiState.PublishError?,
error: NewPostError?,
snackbarHostState: SnackbarHostState,
) {
val context = LocalContext.current
LaunchedEffect(error ?: true) {
if (error != null) {
val errorMessage = when (error) {
is NewPostError.MissingRelaysConfiguration -> context.getString(R.string.app_missing_relays_config)
is NewPostError.PublishError -> context.getString(R.string.new_post_nostr_publish_error)
else -> null
}

if (errorMessage != null) {
snackbarHostState.showSnackbar(
message = context.getString(R.string.new_post_nostr_publish_error),
message = errorMessage,
duration = SnackbarDuration.Short,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import net.primal.android.discuss.post.NewPostContract.UiEvent
import net.primal.android.discuss.post.NewPostContract.UiState
import net.primal.android.feed.repository.PostRepository
import net.primal.android.navigation.newPostPreFillContent
import net.primal.android.networking.relays.errors.MissingRelaysException
import net.primal.android.networking.relays.errors.NostrPublishException
import net.primal.android.nostr.ext.parseEventTags
import net.primal.android.nostr.ext.parseHashtagTags
Expand Down Expand Up @@ -81,13 +82,15 @@ class NewPostViewModel @Inject constructor(
)
sendEffect(SideEffect.PostPublished)
} catch (error: NostrPublishException) {
setErrorState(error = UiState.PublishError(cause = error.cause))
setErrorState(error = UiState.NewPostError.PublishError(cause = error.cause))
} catch (error: MissingRelaysException) {
setErrorState(error = UiState.NewPostError.MissingRelaysConfiguration(cause = error))
} finally {
setState { copy(publishing = false) }
}
}

private fun setErrorState(error: UiState.PublishError) {
private fun setErrorState(error: UiState.NewPostError) {
setState { copy(error = error) }
viewModelScope.launch {
delay(2.seconds)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ interface ExploreFeedContract {
data class FailedToPublishZapEvent(val cause: Throwable) : ExploreFeedError()
data class FailedToPublishRepostEvent(val cause: Throwable) : ExploreFeedError()
data class FailedToPublishLikeEvent(val cause: Throwable) : ExploreFeedError()
data class MissingRelaysConfiguration(val cause: Throwable) : ExploreFeedError()

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ private fun ErrorHandler(
is ExploreFeedError.FailedToPublishZapEvent -> context.getString(R.string.post_action_zap_failed)
is ExploreFeedError.FailedToPublishLikeEvent -> context.getString(R.string.post_action_like_failed)
is ExploreFeedError.FailedToPublishRepostEvent -> context.getString(R.string.post_action_repost_failed)
is ExploreFeedError.MissingRelaysConfiguration -> context.getString(R.string.app_missing_relays_config)
null -> return@LaunchedEffect
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import net.primal.android.explore.feed.ExploreFeedContract.UiState.ExploreFeedEr
import net.primal.android.feed.repository.FeedRepository
import net.primal.android.feed.repository.PostRepository
import net.primal.android.navigation.searchQuery
import net.primal.android.networking.relays.errors.MissingRelaysException
import net.primal.android.networking.relays.errors.NostrPublishException
import net.primal.android.user.accounts.active.ActiveAccountStore
import net.primal.android.user.accounts.active.ActiveUserAccountState
Expand Down Expand Up @@ -115,6 +116,8 @@ class ExploreFeedViewModel @Inject constructor(
)
} catch (error: NostrPublishException) {
setErrorState(error = ExploreFeedError.FailedToPublishLikeEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ExploreFeedError.MissingRelaysConfiguration(error))
}
}

Expand All @@ -127,6 +130,8 @@ class ExploreFeedViewModel @Inject constructor(
)
} catch (error: NostrPublishException) {
setErrorState(error = ExploreFeedError.FailedToPublishRepostEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ExploreFeedError.MissingRelaysConfiguration(error))
}
}

Expand All @@ -151,6 +156,8 @@ class ExploreFeedViewModel @Inject constructor(
setErrorState(error = ExploreFeedError.FailedToPublishZapEvent(error))
} catch (error: NostrPublishException) {
setErrorState(error = ExploreFeedError.FailedToPublishZapEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ExploreFeedError.MissingRelaysConfiguration(error))
} catch (error: ZapRepository.InvalidZapRequestException) {
setErrorState(error = ExploreFeedError.InvalidZapRequest(error))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.primal.android.networking.UserAgentProvider
import net.primal.android.networking.relays.errors.MissingRelaysException
import net.primal.android.networking.relays.errors.NostrPublishException
import net.primal.android.networking.sockets.NostrIncomingMessage
import net.primal.android.networking.sockets.NostrSocketClient
Expand Down Expand Up @@ -71,10 +72,18 @@ class RelayPool @Inject constructor(
when (NostrEventKind.valueOf(nostrEvent.kind)) {
NostrEventKind.ZapRequest,
NostrEventKind.WalletRequest -> {
handlePublishEvent(walletRelays, nostrEvent)
if (walletRelays.isEmpty()) {
throw MissingRelaysException()
} else {
handlePublishEvent(walletRelays, nostrEvent)
}
}
else -> {
handlePublishEvent(regularRelays, nostrEvent)
if (regularRelays.isEmpty()) {
throw MissingRelaysException()
} else {
handlePublishEvent(regularRelays, nostrEvent)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package net.primal.android.networking.relays.errors

class MissingRelaysException : RuntimeException()
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ interface ProfileContract {
data class FailedToPublishZapEvent(val cause: Throwable) : ProfileError()
data class FailedToPublishRepostEvent(val cause: Throwable) : ProfileError()
data class FailedToPublishLikeEvent(val cause: Throwable) : ProfileError()
data class MissingRelaysConfiguration(val cause: Throwable) : ProfileError()
data class FailedToFollowProfile(val cause: Throwable) : ProfileError()
data class FailedToUnfollowProfile(val cause: Throwable) : ProfileError()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,9 @@ private fun ErrorHandler(
is ProfileError.FailedToPublishZapEvent -> context.getString(R.string.post_action_zap_failed)
is ProfileError.FailedToPublishLikeEvent -> context.getString(R.string.post_action_like_failed)
is ProfileError.FailedToPublishRepostEvent -> context.getString(R.string.post_action_repost_failed)
is ProfileError.FailedToFollowProfile -> context.getString(R.string.profile_error_unable_to_follow)
is ProfileError.FailedToUnfollowProfile -> context.getString(R.string.profile_error_unable_to_unfollow)
is ProfileError.MissingRelaysConfiguration -> context.getString(R.string.app_missing_relays_config)
else -> return@LaunchedEffect
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import net.primal.android.core.compose.media.model.MediaResourceUi
import net.primal.android.feed.repository.FeedRepository
import net.primal.android.feed.repository.PostRepository
import net.primal.android.navigation.profileId
import net.primal.android.networking.relays.errors.MissingRelaysException
import net.primal.android.networking.relays.errors.NostrPublishException
import net.primal.android.networking.sockets.errors.WssException
import net.primal.android.profile.db.authorNameUiFriendly
Expand All @@ -27,7 +28,6 @@ import net.primal.android.profile.details.ProfileContract.UiState
import net.primal.android.profile.details.ProfileContract.UiState.ProfileError
import net.primal.android.profile.details.model.ProfileDetailsUi
import net.primal.android.profile.details.model.ProfileStatsUi
import net.primal.android.profile.repository.LatestFollowingResolver
import net.primal.android.profile.repository.ProfileRepository
import net.primal.android.user.accounts.active.ActiveAccountStore
import net.primal.android.wallet.model.ZapTarget
Expand Down Expand Up @@ -153,6 +153,8 @@ class ProfileViewModel @Inject constructor(
)
} catch (error: NostrPublishException) {
setErrorState(error = ProfileError.FailedToPublishLikeEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ProfileError.MissingRelaysConfiguration(error))
}
}

Expand All @@ -165,6 +167,8 @@ class ProfileViewModel @Inject constructor(
)
} catch (error: NostrPublishException) {
setErrorState(error = ProfileError.FailedToPublishRepostEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ProfileError.MissingRelaysConfiguration(error))
}
}

Expand All @@ -189,28 +193,40 @@ class ProfileViewModel @Inject constructor(
setErrorState(error = ProfileError.FailedToPublishZapEvent(error))
} catch (error: NostrPublishException) {
setErrorState(error = ProfileError.FailedToPublishZapEvent(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ProfileError.MissingRelaysConfiguration(error))
} catch (error: ZapRepository.InvalidZapRequestException) {
setErrorState(error = ProfileError.InvalidZapRequest(error))
}
}

private fun follow(followAction: UiEvent.FollowAction) = viewModelScope.launch {
try {
profileRepository.follow(followAction.profileId)
} catch (error: LatestFollowingResolver.RemoteFollowingsUnavailableException) {
// Failed to retrieve latest contacts, propagate error to the UI
profileRepository.follow(
userId = activeAccountStore.activeUserId(),
followedUserId = followAction.profileId,
)
} catch (error: WssException) {
setErrorState(error = ProfileError.FailedToFollowProfile(error))
} catch (error: NostrPublishException) {
// Failed to publish update, propagate error to the UI
setErrorState(error = ProfileError.FailedToFollowProfile(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ProfileError.MissingRelaysConfiguration(error))
}
}

private fun unfollow(unfollowAction: UiEvent.UnfollowAction) = viewModelScope.launch {
try {
profileRepository.unfollow(unfollowAction.profileId)
} catch (error: LatestFollowingResolver.RemoteFollowingsUnavailableException) {
// Failed to retrieve latest contacts, propagate error to the UI
profileRepository.unfollow(
userId = activeAccountStore.activeUserId(),
unfollowedUserId = unfollowAction.profileId,
)
} catch (error: WssException) {
setErrorState(error = ProfileError.FailedToUnfollowProfile(error))
} catch (error: NostrPublishException) {
// Propagate error to the UI
setErrorState(error = ProfileError.FailedToUnfollowProfile(error))
} catch (error: MissingRelaysException) {
setErrorState(error = ProfileError.MissingRelaysConfiguration(error))
}
}

Expand Down

This file was deleted.

Loading

0 comments on commit 7de6813

Please sign in to comment.