Skip to content

Commit

Permalink
Implement profile search (#211)
Browse files Browse the repository at this point in the history
Co-authored-by: Aleksandar Ilic <[email protected]>
  • Loading branch information
markocic and AleksandarIlic authored Oct 22, 2024
1 parent 4b1fa8f commit 0b34012
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package net.primal.android.core.compose.profile.model
import net.primal.android.attachments.domain.CdnImage
import net.primal.android.core.utils.authorNameUiFriendly
import net.primal.android.explore.domain.UserProfileSearchItem
import net.primal.android.profile.db.ProfileData

data class UserProfileItemUi(
val profileId: String,
Expand All @@ -23,3 +24,14 @@ fun UserProfileSearchItem.mapAsUserProfileUi() =
followersCount = this.followersCount,
score = this.score,
)

fun ProfileData.asUserProfileItemUi() =
UserProfileItemUi(
profileId = this.ownerId,
displayName = this.authorNameUiFriendly(),
internetIdentifier = this.internetIdentifier,
avatarCdnImage = this.avatarCdnImage,
followersCount = null,
score = null,
isFollowed = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,29 @@ import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import net.primal.android.core.compose.profile.model.UserProfileItemUi
import net.primal.android.core.compose.profile.model.asUserProfileItemUi
import net.primal.android.crypto.hexToNpubHrp
import net.primal.android.explore.asearch.AdvancedSearchContract.Orientation
import net.primal.android.explore.asearch.AdvancedSearchContract.SearchFilter
import net.primal.android.explore.asearch.AdvancedSearchContract.UiEvent
import net.primal.android.explore.asearch.AdvancedSearchContract.UiState
import net.primal.android.explore.feed.ExploreFeedContract
import net.primal.android.navigation.initialQuery
import net.primal.android.navigation.postedBy
import net.primal.android.profile.repository.ProfileRepository

@HiltViewModel
class AdvancedSearchViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val profileRepository: ProfileRepository,
) : ViewModel() {

companion object {
private const val DATE_FORMAT = "yyyy-MM-dd"
}

private val dateFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT).withZone(ZoneId.systemDefault())
private val initialPostedBy = savedStateHandle.postedBy

private val _state = MutableStateFlow(
UiState(
Expand All @@ -52,6 +57,7 @@ class AdvancedSearchViewModel @Inject constructor(

init {
observeEvents()
fetchInitialPostedBy()
}

private fun observeEvents() =
Expand Down Expand Up @@ -87,6 +93,14 @@ class AdvancedSearchViewModel @Inject constructor(
}
}

private fun fetchInitialPostedBy() =
viewModelScope.launch {
initialPostedBy?.let {
val profiles = profileRepository.findProfilesData(initialPostedBy)
setState { copy(postedBy = profiles.map { it.asUserProfileItemUi() }.toSet()) }
}
}

private fun onSearch() =
viewModelScope.launch {
val uiState = state.value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package net.primal.android.navigation
import androidx.lifecycle.SavedStateHandle
import androidx.navigation.NavBackStackEntry
import net.primal.android.core.serialization.json.NostrJson
import net.primal.android.core.serialization.json.decodeFromStringOrNull
import net.primal.android.explore.search.ui.SearchScope
import net.primal.android.wallet.domain.DraftTx
import net.primal.android.wallet.transactions.send.prepare.tabs.SendPaymentTab
Expand Down Expand Up @@ -30,10 +31,13 @@ inline val SavedStateHandle.renderType: String
const val INITIAL_QUERY = "initialQuery"
inline val SavedStateHandle.initialQuery: String? get() = get(INITIAL_QUERY)

const val POSTED_BY = "postedBy"
inline val SavedStateHandle.postedBy: List<String>?
get() = get<String>(POSTED_BY)?.let {
NostrJson.decodeFromStringOrNull(it)
}

const val SEARCH_SCOPE = "searchScope"
inline val SavedStateHandle.searchScopeOrThrow: SearchScope
get() = get<String>(SEARCH_SCOPE)?.let { SearchScope.valueOf(it) }
?: throw IllegalArgumentException("Missing required searchScope argument.")
inline val NavBackStackEntry.searchScopeOrThrow: SearchScope
get() = arguments?.getString(SEARCH_SCOPE)?.let { SearchScope.valueOf(it) }
?: throw IllegalArgumentException("Missing required searchScope argument.")
Expand Down Expand Up @@ -64,7 +68,7 @@ const val DRAFT_TRANSACTION = "draftTransaction"
inline val SavedStateHandle.draftTransaction: DraftTx
get() = get<String>(DRAFT_TRANSACTION)
?.asBase64Decoded()?.let {
NostrJson.decodeFromString(it)
NostrJson.decodeFromStringOrNull(it)
} ?: throw IllegalArgumentException("Missing draft transaction.")

const val LNBC = "lnbc"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.navigation.navOptions
import java.net.URLEncoder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString
import net.primal.android.articles.reads.ReadsScreen
import net.primal.android.articles.reads.ReadsViewModel
import net.primal.android.attachments.gallery.MediaGalleryScreen
Expand All @@ -41,6 +42,7 @@ import net.primal.android.core.compose.ApplyEdgeToEdge
import net.primal.android.core.compose.LockToOrientationPortrait
import net.primal.android.core.compose.PrimalTopLevelDestination
import net.primal.android.core.compose.findActivity
import net.primal.android.core.serialization.json.NostrJson
import net.primal.android.crypto.hexToNoteHrp
import net.primal.android.drawer.DrawerScreenDestination
import net.primal.android.editor.di.noteEditorViewModel
Expand Down Expand Up @@ -114,8 +116,14 @@ private fun NavController.navigateToLogout() = navigate(route = "logout")
private fun NavController.navigateToSearch(searchScope: SearchScope) =
navigate(route = "search?$SEARCH_SCOPE=$searchScope")

private fun NavController.navigateToAdvancedSearch(initialQuery: String? = null) =
navigate(route = "asearch?$INITIAL_QUERY=$initialQuery")
private fun NavController.navigateToAdvancedSearch(
initialQuery: String? = null,
initialPostedBy: List<String>? = null,
) = navigate(
route = "asearch" +
"?$INITIAL_QUERY=$initialQuery" +
"&$POSTED_BY=${NostrJson.encodeToString(initialPostedBy)}"
)

private fun NavController.navigateToNoteEditor(args: NoteEditorArgs? = null) {
navigate(route = "noteEditor?$NOTE_EDITOR_ARGS=${args?.toJson()?.asBase64Encoded()}")
Expand Down Expand Up @@ -372,13 +380,17 @@ fun PrimalAppNavigation() {
)

advancedSearch(
route = "asearch?$INITIAL_QUERY={$INITIAL_QUERY}",
route = "asearch?$INITIAL_QUERY={$INITIAL_QUERY}&$POSTED_BY={$POSTED_BY}",
navController = navController,
arguments = listOf(
navArgument(INITIAL_QUERY) {
type = NavType.StringType
nullable = true
},
navArgument(POSTED_BY) {
type = NavType.StringType
nullable = true
},
),
)

Expand Down Expand Up @@ -1109,6 +1121,7 @@ private fun NavGraphBuilder.profile(
)
},
onGoToWallet = { navController.navigateToWallet() },
onSearchClick = { navController.navigateToAdvancedSearch(initialPostedBy = listOf(it)) },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import net.primal.android.wallet.domain.DraftTx
fun ProfileDetailsScreen(
viewModel: ProfileDetailsViewModel,
onClose: () -> Unit,
onSearchClick: (String) -> Unit,
noteCallbacks: NoteCallbacks,
onEditProfileClick: () -> Unit,
onMessageClick: (String) -> Unit,
Expand Down Expand Up @@ -126,6 +127,7 @@ fun ProfileDetailsScreen(
state = uiState.value,
snackbarHostState = snackbarHostState,
onClose = onClose,
onSearchClick = onSearchClick,
noteCallbacks = noteCallbacks,
onEditProfileClick = onEditProfileClick,
onMessageClick = onMessageClick,
Expand All @@ -152,6 +154,7 @@ fun ProfileDetailsScreen(
state: ProfileDetailsContract.UiState,
snackbarHostState: SnackbarHostState,
onClose: () -> Unit,
onSearchClick: (String) -> Unit,
noteCallbacks: NoteCallbacks,
onEditProfileClick: () -> Unit,
onMessageClick: (String) -> Unit,
Expand Down Expand Up @@ -294,6 +297,7 @@ fun ProfileDetailsScreen(
eventPublisher = eventPublisher,
onClose = onClose,
paddingValues = paddingValues,
onSearchClick = { onSearchClick(state.profileId) },
)
}
item {
Expand Down Expand Up @@ -521,6 +525,7 @@ private fun PreviewProfileScreen() {
),
snackbarHostState = SnackbarHostState(),
onClose = {},
onSearchClick = {},
noteCallbacks = NoteCallbacks(),
onEditProfileClick = {},
onMessageClick = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
Expand All @@ -36,6 +38,7 @@ import net.primal.android.core.compose.NostrUserText
import net.primal.android.core.compose.PrimalDivider
import net.primal.android.core.compose.icons.PrimalIcons
import net.primal.android.core.compose.icons.primaliconpack.ArrowBack
import net.primal.android.core.compose.icons.primaliconpack.Search
import net.primal.android.core.utils.asEllipsizedNpub
import net.primal.android.profile.details.ProfileDetailsContract
import net.primal.android.theme.AppTheme
Expand All @@ -57,6 +60,7 @@ fun ProfileTopCoverBar(
state: ProfileDetailsContract.UiState,
eventPublisher: (ProfileDetailsContract.UiEvent) -> Unit,
onClose: () -> Unit,
onSearchClick: () -> Unit,
titleVisible: Boolean,
coverValues: CoverValues,
avatarValues: AvatarValues,
Expand Down Expand Up @@ -97,6 +101,7 @@ fun ProfileTopCoverBar(
titleVisible = titleVisible,
eventPublisher = eventPublisher,
paddingValues = paddingValues,
onSearchClick = onSearchClick,
)

Box(
Expand Down Expand Up @@ -129,6 +134,7 @@ private fun ProfileTopAppBar(
titleVisible: Boolean,
eventPublisher: (ProfileDetailsContract.UiEvent) -> Unit,
onClose: () -> Unit,
onSearchClick: () -> Unit,
paddingValues: PaddingValues,
) {
Column(
Expand Down Expand Up @@ -166,12 +172,25 @@ private fun ProfileTopAppBar(
}
},
actions = {
val profileName = state.profileDetails?.authorDisplayName ?: ""
ProfileAppBarIcon(
icon = PrimalIcons.Search,
onClick = onSearchClick,
appBarIconContentDescription = if (profileName.isEmpty()) {
stringResource(id = R.string.accessibility_search)
} else {
stringResource(id = R.string.accessibility_profile_search, profileName)
},
enabledBackgroundColor = Color.Black.copy(alpha = 0.5f),
tint = Color.White,
)
Spacer(modifier = Modifier.width(12.dp))
ProfileDropdownMenu(
profileId = state.profileId,
isActiveUser = state.isActiveUser,
isProfileMuted = state.isProfileMuted,
isProfileFeedInActiveUserFeeds = state.isProfileFeedInActiveUserFeeds,
profileName = state.profileDetails?.authorDisplayName ?: "",
profileName = profileName,
eventPublisher = eventPublisher,
primalName = state.profileDetails?.primalName,
)
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@
<string name="accessibility_note_drop_down">Note drop-down</string>
<string name="accessibility_article_drop_down">Article drop-down</string>
<string name="accessibility_profile_drop_down">Profile drop-down</string>
<string name="accessibility_profile_search">Search notes posted by %1$s</string>
<string name="accessibility_media_drop_down">Media drop-down</string>
<string name="accessibility_feed_picker">Feed picker</string>
<string name="accessibility_search">Search</string>
Expand Down

0 comments on commit 0b34012

Please sign in to comment.