From f5da5c22d1e4060d7c36df5670371cc12e6f9883 Mon Sep 17 00:00:00 2001 From: "maarten.vercruysse" Date: Mon, 25 Dec 2023 17:51:48 +0100 Subject: [PATCH 1/4] Add initial improvements --- app/src/main/java/com/jerboa/Constants.kt | 2 + app/src/main/java/com/jerboa/MainActivity.kt | 9 +- app/src/main/java/com/jerboa/Utils.kt | 3 +- .../main/java/com/jerboa/datatypes/Others.kt | 64 ++-- .../jerboa/model/CommunityListViewModel.kt | 86 ----- .../java/com/jerboa/model/InboxViewModel.kt | 22 +- .../jerboa/model/PersonProfileViewModel.kt | 78 +--- .../java/com/jerboa/model/PostViewModel.kt | 75 +--- .../com/jerboa/model/SearchListViewModel.kt | 183 +++++++++ .../com/jerboa/model/helper/CommentsHelper.kt | 59 +++ .../ui/components/comment/CommentNode.kt | 5 - .../ui/components/comment/CommentNodes.kt | 5 - .../ui/components/common/DropdownMenu.kt | 6 + .../ui/components/common/FormComponents.kt | 84 ++++ .../ui/components/community/CommunityLink.kt | 5 +- .../community/list/CommunityListActivity.kt | 119 ------ .../com/jerboa/ui/components/drawer/Drawer.kt | 3 +- .../ui/components/home/BottomNavActivity.kt | 8 +- .../ui/components/inbox/InboxActivity.kt | 30 +- .../com/jerboa/ui/components/login/Login.kt | 1 + .../person/PersonProfileActivity.kt | 48 ++- .../jerboa/ui/components/post/PostActivity.kt | 3 +- .../post/create/CreatePostActivity.kt | 4 +- .../ui/components/search/SearchActivity.kt | 358 ++++++++++++++++++ .../CommunityList.kt => search/SearchList.kt} | 101 ++--- .../components/search/SearchListPersonItem.kt | 91 +++++ .../search/SearchParametersField.kt | 94 +++++ .../ui/components/search/searchListings.kt | 11 + 28 files changed, 1012 insertions(+), 545 deletions(-) delete mode 100644 app/src/main/java/com/jerboa/model/CommunityListViewModel.kt create mode 100644 app/src/main/java/com/jerboa/model/SearchListViewModel.kt create mode 100644 app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt create mode 100644 app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt delete mode 100644 app/src/main/java/com/jerboa/ui/components/community/list/CommunityListActivity.kt create mode 100644 app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt rename app/src/main/java/com/jerboa/ui/components/{community/list/CommunityList.kt => search/SearchList.kt} (56%) create mode 100644 app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt create mode 100644 app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt create mode 100644 app/src/main/java/com/jerboa/ui/components/search/searchListings.kt diff --git a/app/src/main/java/com/jerboa/Constants.kt b/app/src/main/java/com/jerboa/Constants.kt index 08132680a..8dcc189fd 100644 --- a/app/src/main/java/com/jerboa/Constants.kt +++ b/app/src/main/java/com/jerboa/Constants.kt @@ -3,3 +3,5 @@ package com.jerboa const val DEBOUNCE_DELAY = 1000L const val MAX_POST_TITLE_LENGTH = 200 const val DEFAULT_FONT_SIZE = 16 + +const val COMMENTS_DEPTH_MAX = 6 diff --git a/app/src/main/java/com/jerboa/MainActivity.kt b/app/src/main/java/com/jerboa/MainActivity.kt index e0598fd7d..99f97fa13 100644 --- a/app/src/main/java/com/jerboa/MainActivity.kt +++ b/app/src/main/java/com/jerboa/MainActivity.kt @@ -6,7 +6,6 @@ import android.os.Build import android.os.Bundle import android.util.Patterns import android.widget.TextView -import android.widget.Toast import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity @@ -49,7 +48,7 @@ import com.jerboa.ui.components.common.Route import com.jerboa.ui.components.common.ShowChangelog import com.jerboa.ui.components.common.SwipeToNavigateBack import com.jerboa.ui.components.community.CommunityActivity -import com.jerboa.ui.components.community.list.CommunityListActivity +import com.jerboa.ui.components.search.SearchActivity import com.jerboa.ui.components.community.sidebar.CommunitySidebarActivity import com.jerboa.ui.components.home.BottomNavActivity import com.jerboa.ui.components.home.sidebar.SiteSidebarActivity @@ -366,12 +365,14 @@ class MainActivity : AppCompatActivity() { ), ) { val args = Route.CommunityListArgs(it) - CommunityListActivity( + SearchActivity( appState = appState, - selectMode = args.select, + selectCommunityMode = args.select, blurNSFW = appSettings.blurNSFW, drawerState = drawerState, followList = siteViewModel.getFollowList(), + accountViewModel = accountViewModel, + siteViewModel = siteViewModel, ) } diff --git a/app/src/main/java/com/jerboa/Utils.kt b/app/src/main/java/com/jerboa/Utils.kt index 440b01d61..cebb2dda5 100644 --- a/app/src/main/java/com/jerboa/Utils.kt +++ b/app/src/main/java/com/jerboa/Utils.kt @@ -51,6 +51,7 @@ import coil.annotation.ExperimentalCoilApi import coil.imageLoader import com.jerboa.api.API import com.jerboa.api.ApiState +import com.jerboa.datatypes.getDisplayName import com.jerboa.db.APP_SETTINGS_DEFAULT import com.jerboa.db.entity.AppSettings import com.jerboa.ui.components.common.Route @@ -1098,7 +1099,7 @@ fun showBlockPersonToast( is ApiState.Success -> { Toast.makeText( ctx, - "${blockPersonRes.data.person_view.person.name} Blocked", + "${blockPersonRes.data.person_view.person.getDisplayName()} Blocked", Toast.LENGTH_SHORT, ) .show() diff --git a/app/src/main/java/com/jerboa/datatypes/Others.kt b/app/src/main/java/com/jerboa/datatypes/Others.kt index 670711d58..4e400b604 100644 --- a/app/src/main/java/com/jerboa/datatypes/Others.kt +++ b/app/src/main/java/com/jerboa/datatypes/Others.kt @@ -113,13 +113,11 @@ fun getLocalizedStringForUserTab( ctx: Context, tab: UserTab, ): String { - val returnString = - when (tab) { - UserTab.About -> ctx.getString(R.string.person_profile_activity_about) - UserTab.Posts -> ctx.getString(R.string.person_profile_activity_posts) - UserTab.Comments -> ctx.getString(R.string.person_profile_activity_comments) - } - return returnString + return when (tab) { + UserTab.About -> ctx.getString(R.string.person_profile_activity_about) + UserTab.Posts -> ctx.getString(R.string.person_profile_activity_posts) + UserTab.Comments -> ctx.getString(R.string.person_profile_activity_comments) + } } /** @@ -129,14 +127,12 @@ fun getLocalizedListingTypeName( ctx: Context, listingType: ListingType, ): String { - val returnString = - when (listingType) { - ListingType.All -> ctx.getString(R.string.home_all) - ListingType.Local -> ctx.getString(R.string.home_local) - ListingType.Subscribed -> ctx.getString(R.string.home_subscribed) - ListingType.ModeratorView -> ctx.getString(R.string.home_moderator_view) - } - return returnString + return when (listingType) { + ListingType.All -> ctx.getString(R.string.home_all) + ListingType.Local -> ctx.getString(R.string.home_local) + ListingType.Subscribed -> ctx.getString(R.string.home_subscribed) + ListingType.ModeratorView -> ctx.getString(R.string.home_moderator_view) + } } /** @@ -146,15 +142,13 @@ fun getLocalizedCommentSortTypeName( ctx: Context, commentSortType: CommentSortType, ): String { - val returnString = - when (commentSortType) { - CommentSortType.Hot -> ctx.getString(R.string.sorttype_hot) - CommentSortType.New -> ctx.getString(R.string.sorttype_new) - CommentSortType.Old -> ctx.getString(R.string.sorttype_old) - CommentSortType.Top -> ctx.getString(R.string.dialogs_top) - CommentSortType.Controversial -> ctx.getString(R.string.sorttype_controversial) - } - return returnString + return when (commentSortType) { + CommentSortType.Hot -> ctx.getString(R.string.sorttype_hot) + CommentSortType.New -> ctx.getString(R.string.sorttype_new) + CommentSortType.Old -> ctx.getString(R.string.sorttype_old) + CommentSortType.Top -> ctx.getString(R.string.dialogs_top) + CommentSortType.Controversial -> ctx.getString(R.string.sorttype_controversial) + } } /** @@ -164,12 +158,10 @@ fun getLocalizedUnreadOrAllName( ctx: Context, unreadOrAll: UnreadOrAll, ): String { - val returnString = - when (unreadOrAll) { - UnreadOrAll.Unread -> ctx.getString(R.string.dialogs_unread) - UnreadOrAll.All -> ctx.getString(R.string.dialogs_all) - } - return returnString + return when (unreadOrAll) { + UnreadOrAll.Unread -> ctx.getString(R.string.dialogs_unread) + UnreadOrAll.All -> ctx.getString(R.string.dialogs_all) + } } /** @@ -179,11 +171,9 @@ fun getLocalizedStringForInboxTab( ctx: Context, tab: InboxTab, ): String { - val returnString = - when (tab) { - InboxTab.Replies -> ctx.getString(R.string.inbox_activity_replies) - InboxTab.Mentions -> ctx.getString(R.string.inbox_activity_mentions) - InboxTab.Messages -> ctx.getString(R.string.inbox_activity_messages) - } - return returnString + return when (tab) { + InboxTab.Replies -> ctx.getString(R.string.inbox_activity_replies) + InboxTab.Mentions -> ctx.getString(R.string.inbox_activity_mentions) + InboxTab.Messages -> ctx.getString(R.string.inbox_activity_messages) + } } diff --git a/app/src/main/java/com/jerboa/model/CommunityListViewModel.kt b/app/src/main/java/com/jerboa/model/CommunityListViewModel.kt deleted file mode 100644 index 5e391ea53..000000000 --- a/app/src/main/java/com/jerboa/model/CommunityListViewModel.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.jerboa.model - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.viewModelScope -import androidx.lifecycle.viewmodel.CreationExtras -import com.jerboa.api.API -import com.jerboa.api.ApiState -import com.jerboa.api.toApiState -import it.vercruysse.lemmyapi.dto.SearchType -import it.vercruysse.lemmyapi.dto.SubscribedType -import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityAggregates -import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityFollowerView -import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityView -import it.vercruysse.lemmyapi.v0x19.datatypes.Search -import it.vercruysse.lemmyapi.v0x19.datatypes.SearchResponse -import kotlinx.collections.immutable.ImmutableList -import kotlinx.coroutines.launch - -class CommunityListViewModel(communities: ImmutableList) : ViewModel() { - var searchRes: ApiState by mutableStateOf(ApiState.Empty) - private set - - fun searchCommunities(form: Search) { - viewModelScope.launch { - searchRes = ApiState.Loading - searchRes = API.getInstance().search(form).toApiState() - } - } - - init { - setCommunityListFromFollowed(communities) - } - - private fun setCommunityListFromFollowed(myFollows: ImmutableList) { - // A hack to convert communityFollowerView into CommunityView - val followsIntoCommunityViews = - myFollows.map { cfv -> - CommunityView( - community = cfv.community, - subscribed = SubscribedType.Subscribed, - blocked = false, - counts = - CommunityAggregates( - community_id = cfv.community.id, - subscribers = 0, - posts = 0, - comments = 0, - published = "", - users_active_day = 0, - users_active_week = 0, - users_active_month = 0, - users_active_half_year = 0, - ), - ) - } - - searchRes = - ApiState.Success( - SearchResponse( - type_ = SearchType.Communities, - communities = followsIntoCommunityViews, - comments = emptyList(), - posts = emptyList(), - users = emptyList(), - ), - ) - } - - companion object { - class Factory( - private val followedCommunities: ImmutableList, - ) : ViewModelProvider.Factory { - @Suppress("UNCHECKED_CAST") - override fun create( - modelClass: Class, - extras: CreationExtras, - ): T { - return CommunityListViewModel(followedCommunities) as T - } - } - } -} diff --git a/app/src/main/java/com/jerboa/model/InboxViewModel.kt b/app/src/main/java/com/jerboa/model/InboxViewModel.kt index dd57a814f..68022f026 100644 --- a/app/src/main/java/com/jerboa/model/InboxViewModel.kt +++ b/app/src/main/java/com/jerboa/model/InboxViewModel.kt @@ -21,6 +21,7 @@ import com.jerboa.findAndUpdatePrivateMessage import com.jerboa.getDeduplicateMerge import com.jerboa.showBlockCommunityToast import com.jerboa.showBlockPersonToast +import com.jerboa.util.blockPerson import it.vercruysse.lemmyapi.dto.CommentSortType import it.vercruysse.lemmyapi.v0x19.datatypes.* import kotlinx.coroutines.launch @@ -55,8 +56,6 @@ class InboxViewModel(account: Account, siteViewModel: SiteViewModel) : ViewModel private var markAllAsReadRes: ApiState by mutableStateOf(ApiState.Empty) - private var blockCommunityRes: ApiState by - mutableStateOf(ApiState.Empty) private var blockPersonRes: ApiState by mutableStateOf(ApiState.Empty) @@ -436,27 +435,10 @@ class InboxViewModel(account: Account, siteViewModel: SiteViewModel) : ViewModel } } - fun blockCommunity( - form: BlockCommunity, - ctx: Context, - ) { - viewModelScope.launch { - blockCommunityRes = ApiState.Loading - blockCommunityRes = API.getInstance().blockCommunity(form).toApiState() - showBlockCommunityToast(blockCommunityRes, ctx) - } - } - fun blockPerson( form: BlockPerson, ctx: Context, - ) { - viewModelScope.launch { - blockPersonRes = ApiState.Loading - blockPersonRes = API.getInstance().blockPerson(form).toApiState() - showBlockPersonToast(blockPersonRes, ctx) - } - } + ) = blockPerson(viewModelScope, form, ctx) fun markAllAsRead(onComplete: () -> Unit) { viewModelScope.launch { diff --git a/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt b/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt index db6474214..13214b28c 100644 --- a/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt +++ b/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt @@ -17,25 +17,22 @@ import com.jerboa.api.toApiState import com.jerboa.findAndUpdateComment import com.jerboa.findAndUpdatePost import com.jerboa.getDeduplicateMerge +import com.jerboa.model.helper.CommentsHelper import com.jerboa.showBlockCommunityToast import com.jerboa.showBlockPersonToast import it.vercruysse.lemmyapi.dto.SortType import it.vercruysse.lemmyapi.v0x19.datatypes.* import kotlinx.coroutines.launch -class PersonProfileViewModel(personArg: Either, savedMode: Boolean) : ViewModel() { +class PersonProfileViewModel(personArg: Either, savedMode: Boolean) : ViewModel(), CommentsHelper { var personDetailsRes: ApiState by mutableStateOf(ApiState.Empty) private set private var likePostRes: ApiState by mutableStateOf(ApiState.Empty) private var savePostRes: ApiState by mutableStateOf(ApiState.Empty) private var deletePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var blockCommunityRes: ApiState by mutableStateOf(ApiState.Empty) - private var blockPersonRes: ApiState by mutableStateOf(ApiState.Empty) - private var likeCommentRes: ApiState by mutableStateOf(ApiState.Empty) - private var saveCommentRes: ApiState by mutableStateOf(ApiState.Empty) - private var deleteCommentRes: ApiState by mutableStateOf(ApiState.Empty) + override val scope = viewModelScope private var markPostRes: ApiState by mutableStateOf(ApiState.Empty) @@ -180,73 +177,6 @@ class PersonProfileViewModel(personArg: Either, savedMode: Boo } } - fun blockCommunity( - form: BlockCommunity, - ctx: Context, - ) { - viewModelScope.launch { - blockCommunityRes = ApiState.Loading - blockCommunityRes = API.getInstance().blockCommunity(form).toApiState() - showBlockCommunityToast(blockCommunityRes, ctx) - } - } - - fun blockPerson( - form: BlockPerson, - ctx: Context, - ) { - viewModelScope.launch { - blockPersonRes = ApiState.Loading - blockPersonRes = API.getInstance().blockPerson(form).toApiState() - showBlockPersonToast(blockPersonRes, ctx) - } - } - - fun likeComment(form: CreateCommentLike) { - viewModelScope.launch { - likeCommentRes = ApiState.Loading - likeCommentRes = API.getInstance().createCommentLike(form).toApiState() - - when (val likeRes = likeCommentRes) { - is ApiState.Success -> { - updateComment(likeRes.data.comment_view) - } - - else -> {} - } - } - } - - fun deleteComment(form: DeleteComment) { - viewModelScope.launch { - deleteCommentRes = ApiState.Loading - deleteCommentRes = API.getInstance().deleteComment(form).toApiState() - - when (val deleteRes = deleteCommentRes) { - is ApiState.Success -> { - updateComment(deleteRes.data.comment_view) - } - - else -> {} - } - } - } - - fun saveComment(form: SaveComment) { - viewModelScope.launch { - saveCommentRes = ApiState.Loading - saveCommentRes = API.getInstance().saveComment(form).toApiState() - - when (val saveRes = saveCommentRes) { - is ApiState.Success -> { - updateComment(saveRes.data.comment_view) - } - - else -> {} - } - } - } - fun updatePost(postView: PostView) { when (val existing = personDetailsRes) { is ApiState.Success -> { @@ -260,7 +190,7 @@ class PersonProfileViewModel(personArg: Either, savedMode: Boo } } - fun updateComment(commentView: CommentView) { + override fun updateComment(commentView: CommentView) { when (val existing = personDetailsRes) { is ApiState.Success -> { val newComments = diff --git a/app/src/main/java/com/jerboa/model/PostViewModel.kt b/app/src/main/java/com/jerboa/model/PostViewModel.kt index a721a9781..47218d755 100644 --- a/app/src/main/java/com/jerboa/model/PostViewModel.kt +++ b/app/src/main/java/com/jerboa/model/PostViewModel.kt @@ -10,20 +10,21 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.CreationExtras import arrow.core.Either +import com.jerboa.COMMENTS_DEPTH_MAX import com.jerboa.api.API import com.jerboa.api.ApiState import com.jerboa.api.toApiState import com.jerboa.appendData import com.jerboa.findAndUpdateComment +import com.jerboa.model.helper.CommentsHelper import com.jerboa.showBlockPersonToast import it.vercruysse.lemmyapi.dto.CommentSortType import it.vercruysse.lemmyapi.dto.ListingType import it.vercruysse.lemmyapi.v0x19.datatypes.* +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -const val COMMENTS_DEPTH_MAX = 6 - -class PostViewModel(val id: Either) : ViewModel() { +class PostViewModel(val id: Either) : ViewModel(), CommentsHelper { var postRes: ApiState by mutableStateOf(ApiState.Empty) private set @@ -32,18 +33,14 @@ class PostViewModel(val id: Either) : ViewModel() { var sortType by mutableStateOf(CommentSortType.Hot) private set - private var likeCommentRes: ApiState by mutableStateOf(ApiState.Empty) - private var saveCommentRes: ApiState by mutableStateOf(ApiState.Empty) - private var deleteCommentRes: ApiState by mutableStateOf(ApiState.Empty) - private var likePostRes: ApiState by mutableStateOf(ApiState.Empty) private var savePostRes: ApiState by mutableStateOf(ApiState.Empty) private var deletePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var blockPersonRes: ApiState by mutableStateOf(ApiState.Empty) val unExpandedComments = mutableStateListOf() val commentsWithToggledActionBar = mutableStateListOf() + override val scope: CoroutineScope = viewModelScope init { this.getData() } @@ -126,51 +123,6 @@ class PostViewModel(val id: Either) : ViewModel() { } } - fun likeComment(form: CreateCommentLike) { - viewModelScope.launch { - likeCommentRes = ApiState.Loading - likeCommentRes = API.getInstance().createCommentLike(form).toApiState() - - when (val likeRes = likeCommentRes) { - is ApiState.Success -> { - updateComment(likeRes.data.comment_view) - } - - else -> {} - } - } - } - - fun deleteComment(form: DeleteComment) { - viewModelScope.launch { - deleteCommentRes = ApiState.Loading - deleteCommentRes = API.getInstance().deleteComment(form).toApiState() - - when (val deleteRes = deleteCommentRes) { - is ApiState.Success -> { - updateComment(deleteRes.data.comment_view) - } - - else -> {} - } - } - } - - fun saveComment(form: SaveComment) { - viewModelScope.launch { - saveCommentRes = ApiState.Loading - saveCommentRes = API.getInstance().saveComment(form).toApiState() - - when (val saveRes = saveCommentRes) { - is ApiState.Success -> { - updateComment(saveRes.data.comment_view) - } - - else -> {} - } - } - } - fun likePost(form: CreatePostLike) { viewModelScope.launch { likePostRes = ApiState.Loading @@ -214,18 +166,7 @@ class PostViewModel(val id: Either) : ViewModel() { } } - fun blockPerson( - form: BlockPerson, - ctx: Context, - ) { - viewModelScope.launch { - blockPersonRes = ApiState.Loading - blockPersonRes = API.getInstance().blockPerson(form).toApiState() - showBlockPersonToast(blockPersonRes, ctx) - } - } - - fun updateComment(commentView: CommentView) { + override fun updateComment(commentView: CommentView) { when (val existing = commentsRes) { is ApiState.Success -> { val newComments = @@ -233,9 +174,7 @@ class PostViewModel(val id: Either) : ViewModel() { existing.data.comments, commentView, ) - val newRes = - ApiState.Success(existing.data.copy(comments = newComments)) - commentsRes = newRes + commentsRes = ApiState.Success(existing.data.copy(comments = newComments)) } else -> {} diff --git a/app/src/main/java/com/jerboa/model/SearchListViewModel.kt b/app/src/main/java/com/jerboa/model/SearchListViewModel.kt new file mode 100644 index 000000000..056656b16 --- /dev/null +++ b/app/src/main/java/com/jerboa/model/SearchListViewModel.kt @@ -0,0 +1,183 @@ +package com.jerboa.model + + +import android.content.Context +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.CreationExtras +import com.jerboa.DEBOUNCE_DELAY +import com.jerboa.api.API +import com.jerboa.api.ApiState +import com.jerboa.api.toApiState +import com.jerboa.findAndUpdateComment +import com.jerboa.model.helper.CommentsHelper +import com.jerboa.ui.components.common.apiErrorToast +import it.vercruysse.lemmyapi.dto.ListingType +import it.vercruysse.lemmyapi.dto.SearchType +import it.vercruysse.lemmyapi.dto.SortType +import it.vercruysse.lemmyapi.dto.SubscribedType +import it.vercruysse.lemmyapi.v0x19.datatypes.CommentView +import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityAggregates +import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityFollowerView +import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityView +import it.vercruysse.lemmyapi.v0x19.datatypes.Search +import it.vercruysse.lemmyapi.v0x19.datatypes.SearchResponse +import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +class SearchListViewModel( + communities: ImmutableList, selectCommunityMode: Boolean +) : ViewModel(), CommentsHelper { + + private var fetchSearchJob: Job? = null + var q by mutableStateOf("") + + var searchRes: ApiState by mutableStateOf(ApiState.Empty) + private set + + var currentSearchType by mutableStateOf(SearchType.All) + var currentListing by mutableStateOf(ListingType.All) + var currentSort by mutableStateOf(SortType.New) + + var page by mutableIntStateOf(1) + + override val scope = viewModelScope + override fun updateComment(commentView: CommentView) { + when (val existing = searchRes) { + is ApiState.Success -> { + val newComments = + findAndUpdateComment( + existing.data.comments, + commentView, + ) + searchRes = ApiState.Success(existing.data.copy(comments = newComments)) + } + + else -> {} + } + } + + init { + if (selectCommunityMode) { + setCommunityListFromFollowed(communities) + currentSearchType = SearchType.Communities + currentSort = SortType.TopAll + currentListing = ListingType.Local + } + } + + fun updateSearch() { + fetchSearchJob?.cancel() + fetchSearchJob = viewModelScope.launch { + delay(DEBOUNCE_DELAY) + search() + } + } + + fun onSearchChange(q: String) { + this.q = q + this.page = 1 + updateSearch() + } + + private fun search() { + viewModelScope.launch { + searchRes = ApiState.Loading + searchRes = API.getInstance().search(getForm()).toApiState() + } + } + + private fun getForm(): Search { + return Search( + q = q, + sort = currentSort, + type_ = currentSearchType, + listing_type = currentListing, + page = page, + ) + } + + + private fun setCommunityListFromFollowed(myFollows: ImmutableList) { + // A hack to convert communityFollowerView into CommunityView + val followsIntoCommunityViews = myFollows.map { cfv -> + CommunityView( + community = cfv.community, + subscribed = SubscribedType.Subscribed, + blocked = false, + counts = CommunityAggregates( + community_id = cfv.community.id, + subscribers = 0, + posts = 0, + comments = 0, + published = "", + users_active_day = 0, + users_active_week = 0, + users_active_month = 0, + users_active_half_year = 0, + ), + ) + } + + searchRes = ApiState.Success( + SearchResponse( + type_ = SearchType.Communities, + communities = followsIntoCommunityViews, + comments = emptyList(), + posts = emptyList(), + users = emptyList(), + ), + ) + } + + fun searchNextPage(ctx: Context) { + viewModelScope.launch { + page++ + val res = API.getInstance().search(getForm()) + + res.onSuccess { + when (val oldRes = searchRes) { + is ApiState.Success -> { + searchRes = ApiState.Success( + SearchResponse( + type_ = SearchType.Communities, + communities = oldRes.data.communities + it.communities, + comments = oldRes.data.comments + it.comments, + posts = oldRes.data.posts + it.posts, + users = oldRes.data.users + it.users, + ), + ) + } + + else -> {} + } + }.onFailure { + page-- + apiErrorToast(ctx, it) + } + } + } + + companion object { + class Factory( + private val followedCommunities: ImmutableList, + private val selectCommunityMode: Boolean, + ) : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun create( + modelClass: Class, + extras: CreationExtras, + ): T { + return SearchListViewModel(followedCommunities, selectCommunityMode) as T + } + } + } +} diff --git a/app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt b/app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt new file mode 100644 index 000000000..3d836fab0 --- /dev/null +++ b/app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt @@ -0,0 +1,59 @@ +package com.jerboa.model.helper + +import android.content.Context +import androidx.lifecycle.viewModelScope +import com.jerboa.api.API +import com.jerboa.api.toApiState +import com.jerboa.showBlockPersonToast +import it.vercruysse.lemmyapi.v0x19.datatypes.BlockPerson +import it.vercruysse.lemmyapi.v0x19.datatypes.CommentView +import it.vercruysse.lemmyapi.v0x19.datatypes.CreateCommentLike +import it.vercruysse.lemmyapi.v0x19.datatypes.DeleteComment +import it.vercruysse.lemmyapi.v0x19.datatypes.SaveComment +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +interface CommentsHelper { + + val scope: CoroutineScope + fun updateComment(commentView: CommentView) + fun likeComment(form: CreateCommentLike) { + scope.launch { + val res = API.getInstance().createCommentLike(form) + + res.onSuccess { + updateComment(it.comment_view) + } + } + } + + fun deleteComment(form: DeleteComment) { + scope.launch { + API.getInstance().deleteComment(form).onSuccess { + updateComment(it.comment_view) + } + } + } + + fun saveComment(form: SaveComment) { + scope.launch { + API.getInstance().saveComment(form).onSuccess { + updateComment(it.comment_view) + } + } + } + + fun blockPerson( + form: BlockPerson, + ctx: Context, + ) { + scope.launch { + val blockPersonRes = API.getInstance().blockPerson(form).toApiState() + withContext(Dispatchers.Main) { + showBlockPersonToast(blockPersonRes, ctx) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt b/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt index 1a7a61fb2..29f126b7d 100644 --- a/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt +++ b/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt @@ -181,7 +181,6 @@ fun LazyListScope.commentNodeItem( onDownvoteClick: (commentView: CommentView) -> Unit, onReplyClick: (commentView: CommentView) -> Unit, onSaveClick: (commentView: CommentView) -> Unit, - onMarkAsReadClick: (commentView: CommentView) -> Unit, onCommentClick: (commentView: CommentView) -> Unit, onEditCommentClick: (commentView: CommentView) -> Unit, onDeleteCommentClick: (commentView: CommentView) -> Unit, @@ -391,7 +390,6 @@ fun LazyListScope.commentNodeItem( onUpvoteClick = onUpvoteClick, onDownvoteClick = onDownvoteClick, onSaveClick = onSaveClick, - onMarkAsReadClick = onMarkAsReadClick, onCommentClick = onCommentClick, onEditCommentClick = onEditCommentClick, onDeleteCommentClick = onDeleteCommentClick, @@ -429,7 +427,6 @@ fun LazyListScope.missingCommentNodeItem( onDownvoteClick: (commentView: CommentView) -> Unit, onReplyClick: (commentView: CommentView) -> Unit, onSaveClick: (commentView: CommentView) -> Unit, - onMarkAsReadClick: (commentView: CommentView) -> Unit, onCommentClick: (commentView: CommentView) -> Unit, onEditCommentClick: (commentView: CommentView) -> Unit, onDeleteCommentClick: (commentView: CommentView) -> Unit, @@ -527,7 +524,6 @@ fun LazyListScope.missingCommentNodeItem( onUpvoteClick = onUpvoteClick, onDownvoteClick = onDownvoteClick, onSaveClick = onSaveClick, - onMarkAsReadClick = onMarkAsReadClick, onCommentClick = onCommentClick, onEditCommentClick = onEditCommentClick, onDeleteCommentClick = onDeleteCommentClick, @@ -783,7 +779,6 @@ fun CommentNodesPreview() { onReplyClick = {}, onFetchChildrenClick = {}, onSaveClick = {}, - onMarkAsReadClick = {}, onCommentClick = {}, onEditCommentClick = {}, onDeleteCommentClick = {}, diff --git a/app/src/main/java/com/jerboa/ui/components/comment/CommentNodes.kt b/app/src/main/java/com/jerboa/ui/components/comment/CommentNodes.kt index 0c52ceb11..69f62e75f 100644 --- a/app/src/main/java/com/jerboa/ui/components/comment/CommentNodes.kt +++ b/app/src/main/java/com/jerboa/ui/components/comment/CommentNodes.kt @@ -31,7 +31,6 @@ fun CommentNodes( onDownvoteClick: (commentView: CommentView) -> Unit, onReplyClick: (commentView: CommentView) -> Unit, onSaveClick: (commentView: CommentView) -> Unit, - onMarkAsReadClick: (commentView: CommentView) -> Unit, onCommentClick: (commentView: CommentView) -> Unit, onEditCommentClick: (commentView: CommentView) -> Unit, onDeleteCommentClick: (commentView: CommentView) -> Unit, @@ -68,7 +67,6 @@ fun CommentNodes( onReplyClick = onReplyClick, onSaveClick = onSaveClick, account = account, - onMarkAsReadClick = onMarkAsReadClick, onCommentClick = onCommentClick, onPersonClick = onPersonClick, onHeaderClick = onHeaderClick, @@ -108,7 +106,6 @@ fun LazyListScope.commentNodeItems( onDownvoteClick: (commentView: CommentView) -> Unit, onReplyClick: (commentView: CommentView) -> Unit, onSaveClick: (commentView: CommentView) -> Unit, - onMarkAsReadClick: (commentView: CommentView) -> Unit, onCommentClick: (commentView: CommentView) -> Unit, onEditCommentClick: (commentView: CommentView) -> Unit, onDeleteCommentClick: (commentView: CommentView) -> Unit, @@ -147,7 +144,6 @@ fun LazyListScope.commentNodeItems( onReplyClick = onReplyClick, onSaveClick = onSaveClick, account = account, - onMarkAsReadClick = onMarkAsReadClick, onCommentClick = onCommentClick, onPersonClick = onPersonClick, onHeaderClick = onHeaderClick, @@ -184,7 +180,6 @@ fun LazyListScope.commentNodeItems( onReplyClick = onReplyClick, onSaveClick = onSaveClick, account = account, - onMarkAsReadClick = onMarkAsReadClick, onCommentClick = onCommentClick, onPersonClick = onPersonClick, onHeaderClick = onHeaderClick, diff --git a/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt b/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt index 965f3e08f..69b1cd785 100644 --- a/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt +++ b/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt @@ -8,8 +8,12 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.BarChart import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -46,10 +50,12 @@ fun SortOptionsDropdown( onDismissRequest: () -> Unit, onClickSortType: (SortType) -> Unit, selectedSortType: SortType, + fixedWidth: Dp = 196.dp, ) { CascadeDropdownMenu( expanded = expanded, onDismissRequest = onDismissRequest, + fixedWidth = fixedWidth, modifier = Modifier.semantics { testTagsAsResourceId = true }, ) { getSupportedEntries(API.version).filter { !isTopSort(it) }.forEach { diff --git a/app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt b/app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt new file mode 100644 index 000000000..ef2b68358 --- /dev/null +++ b/app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt @@ -0,0 +1,84 @@ +package com.jerboa.ui.components.common + +import androidx.compose.foundation.clickable +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun ClickableOutlinedTextField( + value: String, + onClick: () -> Unit, + label: @Composable (() -> Unit)? = null, + trailingIcon: @Composable (() -> Unit)? = null, +) { + OutlinedTextField( + value = value, + enabled = false, + readOnly = true, + singleLine = true, + label = label, + onValueChange = {}, + trailingIcon = trailingIcon, + modifier = Modifier.clickable { onClick() }, + colors = OutlinedTextFieldDefaults.colors( + disabledTextColor = MaterialTheme.colorScheme.onSurface, + disabledBorderColor = MaterialTheme.colorScheme.outline, + disabledLeadingIconColor = MaterialTheme.colorScheme.onSurfaceVariant, + disabledTrailingIconColor = MaterialTheme.colorScheme.onSurfaceVariant, + disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant, + disabledPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant, + ) + ) +} + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ReadOnlyDropdown( + expanded: Boolean, + setExpanded: ((Boolean) -> Unit), + states: List, + state: T, + setState: ((T) -> Unit), + stringTransform: (T) -> String = { it.toString() }, + label: String, +) { + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = setExpanded, + ) { + OutlinedTextField( + modifier = Modifier.menuAnchor(), + value = stringTransform(state), + onValueChange = {}, + label = { Text(label) }, + readOnly = true, + singleLine = true, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { setExpanded(false) }, + ) { + states.forEach { selectionOption -> + DropdownMenuItem( + text = { Text(stringTransform(selectionOption)) }, + onClick = { + setState(selectionOption) + setExpanded(false) + }, + contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, + ) + } + } + } +} + diff --git a/app/src/main/java/com/jerboa/ui/components/community/CommunityLink.kt b/app/src/main/java/com/jerboa/ui/components/community/CommunityLink.kt index 2d4b36bf8..bc5f1ec5b 100644 --- a/app/src/main/java/com/jerboa/ui/components/community/CommunityLink.kt +++ b/app/src/main/java/com/jerboa/ui/components/community/CommunityLink.kt @@ -83,7 +83,7 @@ fun CommunityLink( horizontalArrangement = Arrangement.spacedBy(spacing), modifier = if (clickable) { - modifier.clickable { onClick(community) } + Modifier.clickable { onClick(community) }.then(modifier) } else { modifier }, @@ -123,6 +123,7 @@ fun CommunityLinkLarger( onClick: (community: Community) -> Unit, showDefaultIcon: Boolean, blurNSFW: Int, + usersPerMonth: Int? = null, ) { CommunityLink( community = community, @@ -138,6 +139,7 @@ fun CommunityLinkLarger( onClick = onClick, showDefaultIcon = showDefaultIcon, blurNSFW = blurNSFW, + usersPerMonth = usersPerMonth, ) } @@ -159,7 +161,6 @@ fun CommunityLinkLargerWithUserCount( Modifier .padding(LARGE_PADDING) .fillMaxWidth(), - style = MaterialTheme.typography.titleLarge, onClick = onClick, showDefaultIcon = showDefaultIcon, blurNSFW = blurNSFW, diff --git a/app/src/main/java/com/jerboa/ui/components/community/list/CommunityListActivity.kt b/app/src/main/java/com/jerboa/ui/components/community/list/CommunityListActivity.kt deleted file mode 100644 index b6fb02463..000000000 --- a/app/src/main/java/com/jerboa/ui/components/community/list/CommunityListActivity.kt +++ /dev/null @@ -1,119 +0,0 @@ -package com.jerboa.ui.components.community.list - -import android.util.Log -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.DrawerState -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.lifecycle.viewmodel.compose.viewModel -import com.jerboa.DEBOUNCE_DELAY -import com.jerboa.JerboaAppState -import com.jerboa.api.ApiState -import com.jerboa.model.CommunityListViewModel -import com.jerboa.ui.components.common.ApiEmptyText -import com.jerboa.ui.components.common.ApiErrorText -import com.jerboa.ui.components.common.LoadingBar -import it.vercruysse.lemmyapi.dto.SearchType -import it.vercruysse.lemmyapi.dto.SortType -import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityFollowerView -import it.vercruysse.lemmyapi.v0x19.datatypes.Search -import kotlinx.collections.immutable.ImmutableList -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch - -private var fetchCommunitiesJob: Job? = null - -object CommunityListReturn { - const val COMMUNITY = "community-list::return(community)" -} - -@Composable -fun CommunityListActivity( - appState: JerboaAppState, - selectMode: Boolean = false, - followList: ImmutableList, - blurNSFW: Int, - drawerState: DrawerState, -) { - Log.d("jerboa", "got to community list activity") - - val communityListViewModel: CommunityListViewModel = - viewModel(factory = CommunityListViewModel.Companion.Factory(followList)) - - var search by rememberSaveable { mutableStateOf("") } - - val scope = rememberCoroutineScope() - - Surface(color = MaterialTheme.colorScheme.background) { - Scaffold( - topBar = { - CommunityListHeader( - openDrawer = { - scope.launch { - drawerState.open() - } - }, - search = search, - onSearchChange = { - search = it - fetchCommunitiesJob?.cancel() - fetchCommunitiesJob = - scope.launch { - delay(DEBOUNCE_DELAY) - communityListViewModel.searchCommunities( - form = - Search( - q = search, - type_ = SearchType.Communities, - sort = SortType.TopAll, - ), - ) - } - }, - ) - }, - content = { padding -> - when (val communitiesRes = communityListViewModel.searchRes) { - ApiState.Empty -> ApiEmptyText() - is ApiState.Failure -> ApiErrorText(communitiesRes.msg) - ApiState.Loading -> { - LoadingBar(padding) - } - - is ApiState.Success -> { - CommunityListings( - communities = communitiesRes.data.communities, - onClickCommunity = { cs -> - if (selectMode) { - appState.apply { - addReturn(CommunityListReturn.COMMUNITY, cs) - navigateUp() - } - } else { - appState.toCommunity(id = cs.id) - } - }, - modifier = - Modifier - .padding(padding) - .imePadding(), - blurNSFW = blurNSFW, - ) - } - - else -> {} - } - }, - ) - } -} diff --git a/app/src/main/java/com/jerboa/ui/components/drawer/Drawer.kt b/app/src/main/java/com/jerboa/ui/components/drawer/Drawer.kt index 1fd5db82c..ecaccaac9 100644 --- a/app/src/main/java/com/jerboa/ui/components/drawer/Drawer.kt +++ b/app/src/main/java/com/jerboa/ui/components/drawer/Drawer.kt @@ -362,7 +362,7 @@ fun DrawerHeader( accountViewModel: AccountViewModel, myPerson: Person?, onClickShowAccountAddMode: () -> Unit, - showAccountAddMode: Boolean = false, + showAccountAddMode: Boolean, showAvatar: Boolean, ) { val account = getCurrentAccount(accountViewModel) @@ -470,5 +470,6 @@ fun DrawerHeaderPreview() { onClickShowAccountAddMode = {}, showAvatar = true, accountViewModel = accountViewModel, + showAccountAddMode = false, ) } diff --git a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt index da58ce013..d9727609a 100644 --- a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt @@ -50,7 +50,7 @@ import com.jerboa.model.SiteViewModel import com.jerboa.ui.components.common.BottomAppBarAll import com.jerboa.ui.components.common.JerboaSnackbarHost import com.jerboa.ui.components.common.getCurrentAccount -import com.jerboa.ui.components.community.list.CommunityListActivity +import com.jerboa.ui.components.search.SearchActivity import com.jerboa.ui.components.drawer.MainDrawer import com.jerboa.ui.components.inbox.InboxActivity import com.jerboa.ui.components.person.PersonProfileActivity @@ -220,12 +220,14 @@ fun BottomNavActivity( } composable(route = NavTab.Search.name) { - CommunityListActivity( + SearchActivity( appState = appState, - selectMode = false, + selectCommunityMode = false, followList = siteViewModel.getFollowList(), blurNSFW = appSettings.blurNSFW, drawerState = drawerState, + accountViewModel = accountViewModel, + siteViewModel = siteViewModel, ) } diff --git a/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt b/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt index 52826fc9d..dfa3c2e6f 100644 --- a/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt @@ -244,15 +244,7 @@ fun InboxTabs( // act when end of list reached if (endOfListReached) { LaunchedEffect(Unit) { - account.doIfReadyElseDisplayInfo( - appState, - ctx, - snackbarHostState, - scope, - siteViewModel, - ) { - inboxViewModel.appendReplies() - } + inboxViewModel.appendReplies() } } @@ -461,15 +453,7 @@ fun InboxTabs( // act when end of list reached if (endOfListReached) { LaunchedEffect(Unit) { - account.doIfReadyElseDisplayInfo( - appState, - ctx, - snackbarHostState, - scope, - siteViewModel, - ) { - inboxViewModel.appendMentions() - } + inboxViewModel.appendMentions() } } @@ -668,15 +652,7 @@ fun InboxTabs( // act when end of list reached if (endOfListReached) { LaunchedEffect(Unit) { - account.doIfReadyElseDisplayInfo( - appState, - ctx, - snackbarHostState, - scope, - siteViewModel, - ) { - inboxViewModel.appendMessages() - } + inboxViewModel.appendMessages() } } diff --git a/app/src/main/java/com/jerboa/ui/components/login/Login.kt b/app/src/main/java/com/jerboa/ui/components/login/Login.kt index 873d31f66..3b487d48c 100644 --- a/app/src/main/java/com/jerboa/ui/components/login/Login.kt +++ b/app/src/main/java/com/jerboa/ui/components/login/Login.kt @@ -58,6 +58,7 @@ import it.vercruysse.lemmyapi.v0x19.datatypes.Login import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +@OptIn(ExperimentalComposeUiApi::class) @Composable fun MyTextField( modifier: Modifier = Modifier, diff --git a/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt b/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt index 8b1208f92..57f8ceab2 100644 --- a/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt @@ -33,6 +33,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment @@ -138,6 +139,7 @@ fun PersonProfileActivity( personProfileViewModel.insertComment(cv) } } + else -> {} } } @@ -171,16 +173,17 @@ fun PersonProfileActivity( matrixId = null, ) } + is ApiState.Holder -> { val person = profileRes.data.person_view.person PersonProfileHeader( scrollBehavior = scrollBehavior, personName = - if (savedMode) { - ctx.getString(R.string.bookmarks_activity_saved) - } else { - person.name - }, + if (savedMode) { + ctx.getString(R.string.bookmarks_activity_saved) + } else { + person.name + }, myProfile = account.id == person.id, selectedSortType = personProfileViewModel.sortType, onClickSortType = { sortType -> @@ -235,6 +238,7 @@ fun PersonProfileActivity( matrixId = person.matrix_user_id, ) } + else -> {} } }, @@ -327,6 +331,7 @@ fun UserTabs( ApiState.Refreshing, ) } + else -> {} } }, @@ -382,9 +387,9 @@ fun UserTabs( LazyColumn( state = listState, modifier = - Modifier - .fillMaxSize() - .simpleVerticalScrollbar(listState), + Modifier + .fillMaxSize() + .simpleVerticalScrollbar(listState), ) { item(contentType = "topSection") { PersonProfileTopSection( @@ -420,6 +425,7 @@ fun UserTabs( } } } + else -> {} } } @@ -427,9 +433,9 @@ fun UserTabs( UserTab.Posts.ordinal -> { Box( modifier = - Modifier - .pullRefresh(pullRefreshState) - .fillMaxSize(), + Modifier + .pullRefresh(pullRefreshState) + .fillMaxSize(), ) { JerboaPullRefreshIndicator( personProfileViewModel.personDetailsRes.isRefreshing(), @@ -461,10 +467,10 @@ fun UserTabs( CreatePostLike( post_id = pv.post.id, score = - newVote( - pv.my_vote, - VoteType.Upvote, - ), + newVote( + pv.my_vote, + VoteType.Upvote, + ), ), ) } @@ -481,10 +487,10 @@ fun UserTabs( CreatePostLike( post_id = pv.post.id, score = - newVote( - pv.my_vote, - VoteType.Downvote, - ), + newVote( + pv.my_vote, + VoteType.Downvote, + ), ), ) } @@ -571,6 +577,7 @@ fun UserTabs( showPostAppendRetry = personProfileViewModel.personDetailsRes is ApiState.AppendingFailure, ) } + else -> {} } } @@ -583,7 +590,7 @@ fun UserTabs( ApiState.Loading -> LoadingBar() ApiState.Refreshing -> LoadingBar() is ApiState.Holder -> { - val nodes = commentsToFlatNodes(profileRes.data.comments) + val nodes by remember { mutableStateOf(commentsToFlatNodes(profileRes.data.comments)) } val listState = rememberLazyListState() @@ -651,7 +658,6 @@ fun UserTabs( listState = listState, toggleExpanded = { commentId -> toggleExpanded(commentId) }, toggleActionBar = { commentId -> toggleActionBar(commentId) }, - onMarkAsReadClick = {}, onCommentClick = { cv -> appState.toComment(id = cv.comment.id) }, diff --git a/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt b/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt index ed29e3c9f..384409d32 100644 --- a/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt @@ -480,7 +480,6 @@ fun PostActivity( }, toggleExpanded = toggleExpanded, toggleActionBar = toggleActionBar, - onMarkAsReadClick = {}, onCommentClick = { commentView -> toggleExpanded(commentView.comment.id) }, onUpvoteClick = { cv -> account.doIfReadyElseDisplayInfo( @@ -607,6 +606,7 @@ fun PostActivity( account = account, enableDownVotes = siteViewModel.enableDownvotes(), showAvatar = siteViewModel.showAvatar(), + showScores = siteViewModel.showScores(), isCollapsedByParent = false, showCollapsedCommentContent = showCollapsedCommentContent, showActionBar = { commentId -> @@ -616,7 +616,6 @@ fun PostActivity( ) }, blurNSFW = blurNSFW, - showScores = siteViewModel.showScores(), ) item { Spacer(modifier = Modifier.height(100.dp)) diff --git a/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt b/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt index 9b49d175b..b2aeb0911 100644 --- a/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt @@ -35,7 +35,7 @@ import com.jerboa.padUrlWithHttps import com.jerboa.ui.components.common.ActionTopBar import com.jerboa.ui.components.common.LoadingBar import com.jerboa.ui.components.common.getCurrentAccount -import com.jerboa.ui.components.community.list.CommunityListReturn +import com.jerboa.ui.components.search.SearchListReturn import com.jerboa.ui.components.post.composables.CreateEditPostBody import com.jerboa.ui.components.post.composables.PostCommunitySelector import com.jerboa.validatePostName @@ -77,7 +77,7 @@ fun CreatePostActivity( } // On return from the community picker - appState.ConsumeReturn(CommunityListReturn.COMMUNITY) { community -> + appState.ConsumeReturn(SearchListReturn.COMMUNITY) { community -> selectedCommunity = community } diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt new file mode 100644 index 000000000..a4bc3639d --- /dev/null +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt @@ -0,0 +1,358 @@ +package com.jerboa.ui.components.search + +import android.util.Log +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.DrawerState +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.lifecycle.viewmodel.compose.viewModel +import com.jerboa.JerboaAppState +import com.jerboa.VoteType +import com.jerboa.api.ApiState +import com.jerboa.commentsToFlatNodes +import com.jerboa.feat.doIfReadyElseDisplayInfo +import com.jerboa.isScrolledToEnd +import com.jerboa.model.AccountViewModel +import com.jerboa.model.ReplyItem +import com.jerboa.model.SearchListViewModel +import com.jerboa.model.SiteViewModel +import com.jerboa.newVote +import com.jerboa.ui.components.comment.commentNodeItems +import com.jerboa.ui.components.common.ApiErrorText +import com.jerboa.ui.components.common.JerboaSnackbarHost +import com.jerboa.ui.components.common.LoadingBar +import com.jerboa.ui.components.common.getCurrentAccount +import com.jerboa.ui.components.common.simpleVerticalScrollbar +import it.vercruysse.lemmyapi.v0x19.datatypes.BlockPerson +import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityFollowerView +import it.vercruysse.lemmyapi.v0x19.datatypes.CreateCommentLike +import it.vercruysse.lemmyapi.v0x19.datatypes.DeleteComment +import it.vercruysse.lemmyapi.v0x19.datatypes.SaveComment +import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.launch + +object SearchListReturn { + const val COMMUNITY = "search-list::return(community)" +} + +@Composable +fun SearchActivity( + appState: JerboaAppState, + selectCommunityMode: Boolean = false, + followList: ImmutableList, + blurNSFW: Int, + drawerState: DrawerState, + accountViewModel: AccountViewModel, + siteViewModel: SiteViewModel, +) { + Log.d("SearchActivity", "Arrived") + + val ctx = LocalContext.current + val account = getCurrentAccount(accountViewModel) + val snackbarHostState = remember { SnackbarHostState() } + val scope = rememberCoroutineScope() + + var showSearchOptions by rememberSaveable { mutableStateOf(false) } + val searchListViewModel: SearchListViewModel = + viewModel(factory = SearchListViewModel.Companion.Factory(followList, selectCommunityMode)) + + Surface(color = MaterialTheme.colorScheme.background) { + Scaffold( + topBar = { + SearchListHeader( + showSearchOptions = showSearchOptions, + setShowSearchOptions = { showSearchOptions = it }, + openDrawer = { + appState.coroutineScope.launch { + drawerState.open() + } + }, + search = searchListViewModel.q, + onSearchChange = searchListViewModel::onSearchChange, + ) + }, + snackbarHost = { JerboaSnackbarHost(snackbarHostState) }, + content = { padding -> + + Column( + Modifier.padding(padding).imePadding(), + ) { + AnimatedVisibility( + visible = showSearchOptions, + enter = expandVertically(), + exit = shrinkVertically(), + ) { + Column( + Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + SearchParametersField( + currentSort = searchListViewModel.currentSort, + setCurrentSort = { + searchListViewModel.currentSort = it + searchListViewModel.updateSearch() + }, + currentSearchType = searchListViewModel.currentSearchType, + setCurrentSearchType = { + searchListViewModel.currentSearchType = it + searchListViewModel.updateSearch() + }, + currentListing = searchListViewModel.currentListing, + setCurrentListing = { + searchListViewModel.currentListing = it + searchListViewModel.updateSearch() + }, + ) + } + + } + + when (val communitiesRes = searchListViewModel.searchRes) { + is ApiState.Failure -> ApiErrorText(communitiesRes.msg) + ApiState.Loading -> { + LoadingBar() + } + + is ApiState.Success -> { + + val listState = rememberLazyListState() + + val endOfListReached by remember { + derivedStateOf { + listState.isScrolledToEnd() + } + } + + if (endOfListReached) { + LaunchedEffect(Unit) { + searchListViewModel.searchNextPage(ctx) + } + } + + val nodes by remember { mutableStateOf(commentsToFlatNodes(communitiesRes.data.comments)) } + + + // Holds the un-expanded comment ids + val unExpandedComments = remember { mutableStateListOf() } + val commentsWithToggledActionBar = remember { mutableStateListOf() } + + val toggleExpanded = { commentId: Int -> + if (unExpandedComments.contains(commentId)) { + unExpandedComments.remove(commentId) + } else { + unExpandedComments.add(commentId) + } + } + + val toggleActionBar = { commentId: Int -> + if (commentsWithToggledActionBar.contains(commentId)) { + commentsWithToggledActionBar.remove(commentId) + } else { + commentsWithToggledActionBar.add(commentId) + } + } + + val showActionBarByDefault = true + + + + LazyColumn( + state = listState, + modifier = Modifier.simpleVerticalScrollbar(listState), + ) { + searchPersonListings( + personViews = communitiesRes.data.users, + onPersonClick = { personView -> + appState.toProfile(id = personView.person.id) + }, + ) + searchCommunityListings( + communities = communitiesRes.data.communities, + onClickCommunity = { cs -> + if (selectCommunityMode) { + appState.apply { + addReturn(SearchListReturn.COMMUNITY, cs) + navigateUp() + } + } else { + appState.toCommunity(id = cs.id) + } + }, + blurNSFW = blurNSFW, + ) + + commentNodeItems( + nodes = nodes, + increaseLazyListIndexTracker = {}, + addToParentIndexes = {}, + isFlat = true, + isExpanded = { commentId -> !unExpandedComments.contains(commentId) }, + toggleExpanded = { commentId -> toggleExpanded(commentId) }, + toggleActionBar = { commentId -> toggleActionBar(commentId) }, + onCommentClick = { cv -> + appState.toComment(id = cv.comment.id) + }, + onUpvoteClick = { cv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + loginAsToast = true, + ) { + searchListViewModel.likeComment( + CreateCommentLike( + comment_id = cv.comment.id, + score = newVote(cv.my_vote, VoteType.Upvote), + ), + ) + } + }, + onDownvoteClick = { cv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + loginAsToast = true, + ) { + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + loginAsToast = true, + ) { + searchListViewModel.likeComment( + CreateCommentLike( + comment_id = cv.comment.id, + score = newVote(cv.my_vote, VoteType.Downvote), + ), + ) + } + } + }, + onReplyClick = { cv -> + appState.toCommentReply( + replyItem = ReplyItem.CommentItem(cv), + ) + }, + onSaveClick = { cv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + loginAsToast = true, + ) { + searchListViewModel.saveComment( + SaveComment( + comment_id = cv.comment.id, + save = !cv.saved, + ), + ) + } + }, + onPersonClick = appState::toProfile, + onHeaderClick = {}, + onHeaderLongClick = { commentView -> toggleActionBar(commentView.comment.id) }, + onCommunityClick = { community -> + appState.toCommunity(id = community.id) + }, + onPostClick = { postId -> + appState.toPost(id = postId) + }, + onEditCommentClick = { cv -> + appState.toCommentEdit( + commentView = cv, + ) + }, + onDeleteCommentClick = { cv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + loginAsToast = true, + ) { + searchListViewModel.deleteComment( + DeleteComment( + comment_id = cv.comment.id, + deleted = !cv.comment.deleted, + ), + ) + } + }, + onReportClick = { cv -> + appState.toCommentReport(id = cv.comment.id) + }, + onCommentLinkClick = { cv -> + appState.toComment(id = cv.comment.id) + }, + onFetchChildrenClick = {}, + onBlockCreatorClick = { person -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + loginAsToast = true, + ) { + searchListViewModel.blockPerson( + BlockPerson( + person_id = person.id, + block = true, + ), + ctx, + ) + } + }, + showPostAndCommunityContext = true, + showCollapsedCommentContent = true, + isCollapsedByParent = false, + showActionBar = { commentId -> + showActionBarByDefault xor commentsWithToggledActionBar.contains(commentId) + }, + account = account, + enableDownVotes = siteViewModel.enableDownvotes(), + showAvatar = siteViewModel.showAvatar(), + showScores = siteViewModel.showScores(), + blurNSFW = blurNSFW, + ) + } + + + } + + else -> {} + } + } + + + }, + ) + } +} diff --git a/app/src/main/java/com/jerboa/ui/components/community/list/CommunityList.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt similarity index 56% rename from app/src/main/java/com/jerboa/ui/components/community/list/CommunityList.kt rename to app/src/main/java/com/jerboa/ui/components/search/SearchList.kt index d41d13bd8..54d3081e3 100644 --- a/app/src/main/java/com/jerboa/ui/components/community/list/CommunityList.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt @@ -1,9 +1,8 @@ -package com.jerboa.ui.components.community.list +package com.jerboa.ui.components.search import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.* @@ -22,35 +21,32 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview import com.jerboa.R -import com.jerboa.datatypes.sampleCommunityView -import com.jerboa.ui.components.common.simpleVerticalScrollbar import com.jerboa.ui.components.community.CommunityLinkLarger import com.jerboa.ui.components.community.CommunityLinkLargerWithUserCount import it.vercruysse.lemmyapi.v0x19.datatypes.* @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CommunityListHeader( +fun SearchListHeader( openDrawer: () -> Unit, search: String, onSearchChange: (search: String) -> Unit, + showSearchOptions: Boolean, + setShowSearchOptions: (Boolean) -> Unit, ) { TopAppBar( title = { - CommunityTopBarSearchView( + TopBarSearchField( search = search, onSearchChange = onSearchChange, ) }, actions = { - // TODO: disabled until ever implemented IconButton( - enabled = false, - onClick = { - }, + onClick = { setShowSearchOptions(!showSearchOptions) }, ) { Icon( - imageVector = Icons.Outlined.MoreVert, + imageVector = if (showSearchOptions) Icons.Outlined.ExpandMore else Icons.Outlined.ExpandLess, contentDescription = stringResource(R.string.moreOptions), ) } @@ -66,57 +62,29 @@ fun CommunityListHeader( ) } -@Composable -fun CommunityListings( +fun LazyListScope. searchCommunityListings( communities: List, onClickCommunity: (community: Community) -> Unit, - modifier: Modifier = Modifier, blurNSFW: Int, ) { - val listState = rememberLazyListState() - - LazyColumn( - state = listState, - modifier = modifier.simpleVerticalScrollbar(listState), - ) { - items( - communities, - key = { it.community.id }, - contentType = { "communitylink" }, - ) { item -> + items( + communities, + contentType = { "communitylink" }, + ) { item -> + CommunityLinkLarger( + community = item.community, + onClick = onClickCommunity, + showDefaultIcon = true, + blurNSFW = blurNSFW, // A hack for the community follower views that were coerced into community views without counts - if (item.counts.users_active_month == 0) { - CommunityLinkLarger( - community = item.community, - onClick = onClickCommunity, - showDefaultIcon = true, - blurNSFW = blurNSFW, - ) - } else { - CommunityLinkLargerWithUserCount( - communityView = item, - onClick = onClickCommunity, - showDefaultIcon = true, - blurNSFW = blurNSFW, - ) - } - } + usersPerMonth = if (item.counts.users_active_month == 0) null + else item.counts.users_active_month, + ) } } -@Preview -@Composable -fun CommunityListingsPreview() { - val communities = listOf(sampleCommunityView, sampleCommunityView) - CommunityListings( - communities = communities, - onClickCommunity = {}, - blurNSFW = 1, - ) -} - @Composable -fun CommunityTopBarSearchView( +fun TopBarSearchField( search: String, onSearchChange: (search: String) -> Unit, ) { @@ -127,9 +95,7 @@ fun CommunityTopBarSearchView( placeholder = { Text(stringResource(R.string.community_list_search)) }, - modifier = - Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), trailingIcon = { if (search.isNotEmpty()) { IconButton( @@ -143,16 +109,15 @@ fun CommunityTopBarSearchView( } }, singleLine = true, - colors = - TextFieldDefaults.colors( - focusedContainerColor = Color.Transparent, - unfocusedContainerColor = Color.Transparent, - disabledContainerColor = Color.Transparent, - errorContainerColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - ), + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.Transparent, + unfocusedContainerColor = Color.Transparent, + disabledContainerColor = Color.Transparent, + errorContainerColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + ), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), ) } @@ -160,7 +125,7 @@ fun CommunityTopBarSearchView( @Preview(showBackground = true) @Composable fun SearchViewPreview() { - CommunityTopBarSearchView( + TopBarSearchField( search = "", onSearchChange = {}, ) diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt new file mode 100644 index 000000000..695c54f37 --- /dev/null +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt @@ -0,0 +1,91 @@ +package com.jerboa.ui.components.search + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Person +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import com.jerboa.personNameShown +import com.jerboa.ui.components.common.CircularIcon +import com.jerboa.ui.components.person.CommentsAndPosts +import com.jerboa.ui.theme.DRAWER_ITEM_SPACING +import com.jerboa.ui.theme.ICON_SIZE +import com.jerboa.ui.theme.ICON_THUMBNAIL_SIZE +import com.jerboa.ui.theme.LARGER_ICON_THUMBNAIL_SIZE +import com.jerboa.ui.theme.LARGE_PADDING +import com.jerboa.ui.theme.LINK_ICON_SIZE +import com.jerboa.ui.theme.SMALL_PADDING +import it.vercruysse.lemmyapi.v0x19.datatypes.PersonView + + +@Composable +fun SearchListPersonItem( + personView: PersonView, + onClickPerson: (PersonView) -> Unit, + spacing: Dp = DRAWER_ITEM_SPACING, + size: Dp = LINK_ICON_SIZE, + thumbnailSize: Int = LARGER_ICON_THUMBNAIL_SIZE, +) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(spacing), + modifier = Modifier + .clickable { onClickPerson(personView) } + .padding(LARGE_PADDING) + .fillMaxWidth(), + ) { + val avatar = personView.person.avatar + + if (avatar != null) { + CircularIcon( + icon = avatar, + contentDescription = null, + size = size, + thumbnailSize = thumbnailSize, + ) + } else { + Icon( + imageVector = Icons.Outlined.Person, + contentDescription = "", + modifier = Modifier.size(size), + ) + } + + Column { + PersonName(personView) + CommentsAndPosts(personView) + } + } +} + +@Composable +fun PersonName( + person: PersonView, + modifier: Modifier = Modifier, + color: Color = MaterialTheme.colorScheme.primary, + style: TextStyle = MaterialTheme.typography.bodyMedium, + overflow: TextOverflow = TextOverflow.Ellipsis, +) { + Text( + text = personNameShown(person.person, true), + style = style, + color = color, + modifier = modifier, + overflow = overflow, + maxLines = 1, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt new file mode 100644 index 000000000..041a67c7c --- /dev/null +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt @@ -0,0 +1,94 @@ +package com.jerboa.ui.components.search + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.jerboa.datatypes.data +import com.jerboa.datatypes.getLocalizedListingTypeName +import com.jerboa.ui.components.common.ClickableOutlinedTextField +import com.jerboa.ui.components.common.ReadOnlyDropdown +import com.jerboa.ui.components.common.SortOptionsDropdown +import it.vercruysse.lemmyapi.dto.ListingType +import it.vercruysse.lemmyapi.dto.SearchType +import it.vercruysse.lemmyapi.dto.SortType + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SearchParametersField( + currentSort: SortType, setCurrentSort: (SortType) -> Unit, + currentSearchType: SearchType, setCurrentSearchType: (SearchType) -> Unit, + currentListing: ListingType, setCurrentListing: (ListingType) -> Unit +) { + val ctx = LocalContext.current + + var expandedListing by rememberSaveable { mutableStateOf(false) } + var expandedSearchType by rememberSaveable { mutableStateOf(false) } + var expandedSort by rememberSaveable { mutableStateOf(false) } + + Column( + modifier = Modifier + .padding(16.dp, 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + + Box { + ClickableOutlinedTextField( + value = stringResource(currentSort.data.shortForm), + label = { Text("Sort By") }, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expandedSort) }, + onClick = { expandedSort = true }, + ) + + SortOptionsDropdown( + expanded = expandedSort, + onDismissRequest = { expandedSort = false }, + onClickSortType = { + expandedSort = false + setCurrentSort(it) + }, + selectedSortType = currentSort, + fixedWidth = OutlinedTextFieldDefaults.MinWidth + ) + } + + ReadOnlyDropdown( + expanded = expandedSearchType, + setExpanded = { expandedSearchType = it }, + states = SearchType.entries, + state = currentSearchType, + setState = setCurrentSearchType, + label = "Search In", // TODO + stringTransform = { it.name }, + ) + ReadOnlyDropdown( + expanded = expandedListing, + setExpanded = { expandedListing = it }, + states = ListingType.entries, + state = currentListing, + setState = setCurrentListing, + label = "Limit To", // TODO + stringTransform = { getLocalizedListingTypeName(ctx, it) }, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jerboa/ui/components/search/searchListings.kt b/app/src/main/java/com/jerboa/ui/components/search/searchListings.kt new file mode 100644 index 000000000..04edc68e2 --- /dev/null +++ b/app/src/main/java/com/jerboa/ui/components/search/searchListings.kt @@ -0,0 +1,11 @@ +package com.jerboa.ui.components.search + +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.items +import it.vercruysse.lemmyapi.v0x19.datatypes.PersonView + +fun LazyListScope.searchPersonListings(personViews: List, onPersonClick: (PersonView) -> Unit){ + items(personViews) { personView -> + SearchListPersonItem(personView = personView, onClickPerson = onPersonClick) + } +} From cbf70bc65c8dcc970c47b22d9851037fdbf1367c Mon Sep 17 00:00:00 2001 From: "maarten.vercruysse" Date: Mon, 25 Dec 2023 21:02:15 +0100 Subject: [PATCH 2/4] Do cleanup --- .editorconfig | 5 +- app/src/main/java/com/jerboa/MainActivity.kt | 2 +- .../main/java/com/jerboa/datatypes/Others.kt | 18 +++-- .../java/com/jerboa/datatypes/SampleData.kt | 4 +- .../main/java/com/jerboa/datatypes/Utils.kt | 1 - .../java/com/jerboa/model/InboxViewModel.kt | 5 +- .../jerboa/model/PersonProfileViewModel.kt | 5 +- .../java/com/jerboa/model/PostViewModel.kt | 5 +- .../com/jerboa/model/SearchListViewModel.kt | 72 ++++++++++--------- .../com/jerboa/model/helper/CommentsHelper.kt | 6 +- .../ui/components/common/DropdownMenu.kt | 4 -- .../ui/components/common/FormComponents.kt | 19 +++-- .../ui/components/community/Community.kt | 2 +- .../ui/components/home/BottomNavActivity.kt | 2 +- .../ui/components/person/PersonProfile.kt | 2 +- .../person/PersonProfileActivity.kt | 38 +++++----- .../post/create/CreatePostActivity.kt | 2 +- .../ui/components/search/SearchActivity.kt | 9 --- .../jerboa/ui/components/search/SearchList.kt | 30 ++++---- .../components/search/SearchListPersonItem.kt | 15 ++-- .../{searchListings.kt => SearchListings.kt} | 5 +- .../search/SearchParametersField.kt | 31 ++++---- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-az/strings.xml | 1 - app/src/main/res/values-bg/strings.xml | 1 - app/src/main/res/values-da/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-nn/strings.xml | 3 +- app/src/main/res/values-pl/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-se/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values/strings.xml | 3 +- 40 files changed, 132 insertions(+), 172 deletions(-) rename app/src/main/java/com/jerboa/ui/components/search/{searchListings.kt => SearchListings.kt} (73%) diff --git a/.editorconfig b/.editorconfig index 0a8760a73..a674f0ed5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,9 +6,8 @@ ktlint_standard_if-else-wrapping = disabled ktlint_standard_no-wildcard-imports = disabled ktlint_standard_comment-wrapping = disabled ktlint_function_naming_ignore_when_annotated_with=Composable - -[app/src/main/java/com/jerboa/datatypes/**.{kt,kts}] -ktlint = disabled +ktlint_standard_multiline-expression-wrapping = disabled +ktlint_standard_string-template-indent = disabled [app/src/main/java/com/jerboa/DefaultInstances.kt] ktlint = disabled diff --git a/app/src/main/java/com/jerboa/MainActivity.kt b/app/src/main/java/com/jerboa/MainActivity.kt index 99f97fa13..b6f9941ac 100644 --- a/app/src/main/java/com/jerboa/MainActivity.kt +++ b/app/src/main/java/com/jerboa/MainActivity.kt @@ -48,7 +48,6 @@ import com.jerboa.ui.components.common.Route import com.jerboa.ui.components.common.ShowChangelog import com.jerboa.ui.components.common.SwipeToNavigateBack import com.jerboa.ui.components.community.CommunityActivity -import com.jerboa.ui.components.search.SearchActivity import com.jerboa.ui.components.community.sidebar.CommunitySidebarActivity import com.jerboa.ui.components.home.BottomNavActivity import com.jerboa.ui.components.home.sidebar.SiteSidebarActivity @@ -63,6 +62,7 @@ import com.jerboa.ui.components.privatemessage.CreatePrivateMessageActivity import com.jerboa.ui.components.privatemessage.PrivateMessageReplyActivity import com.jerboa.ui.components.report.comment.CreateCommentReportActivity import com.jerboa.ui.components.report.post.CreatePostReportActivity +import com.jerboa.ui.components.search.SearchActivity import com.jerboa.ui.components.settings.SettingsActivity import com.jerboa.ui.components.settings.about.AboutActivity import com.jerboa.ui.components.settings.account.AccountSettingsActivity diff --git a/app/src/main/java/com/jerboa/datatypes/Others.kt b/app/src/main/java/com/jerboa/datatypes/Others.kt index 4e400b604..0c8a3878d 100644 --- a/app/src/main/java/com/jerboa/datatypes/Others.kt +++ b/app/src/main/java/com/jerboa/datatypes/Others.kt @@ -21,7 +21,6 @@ import it.vercruysse.lemmyapi.dto.CommentSortType import it.vercruysse.lemmyapi.dto.ListingType import it.vercruysse.lemmyapi.dto.SortType - data class CommentSortData( @StringRes val text: Int, val icon: ImageVector, @@ -51,7 +50,7 @@ val SortType.data: SortData SortType.Controversial -> SortData( R.string.sorttype_controversial, R.string.sorttype_controversial, - Icons.Outlined.ThumbsUpDown + Icons.Outlined.ThumbsUpDown, ) SortType.TopDay -> SortData(R.string.sorttype_topday, R.string.dialogs_top_day, Icons.Outlined.BarChart) @@ -62,50 +61,49 @@ val SortType.data: SortData SortType.MostComments -> SortData( R.string.sorttype_mostcomments, R.string.sorttype_mostcomments, - Icons.Outlined.FormatListNumbered + Icons.Outlined.FormatListNumbered, ) SortType.NewComments -> SortData( R.string.sorttype_newcomments, R.string.sorttype_newcomments, - Icons.Outlined.NewReleases + Icons.Outlined.NewReleases, ) SortType.TopHour -> SortData(R.string.sorttype_tophour, R.string.dialogs_top_hour, Icons.Outlined.BarChart) SortType.TopSixHour -> SortData( R.string.sorttype_topsixhour, R.string.dialogs_top_six_hour, - Icons.Outlined.BarChart + Icons.Outlined.BarChart, ) SortType.TopTwelveHour -> SortData( R.string.sorttype_toptwelvehour, R.string.dialogs_top_twelve_hour, - Icons.Outlined.BarChart + Icons.Outlined.BarChart, ) SortType.TopThreeMonths -> SortData( R.string.sorttype_topthreemonths, R.string.dialogs_top_three_month, - Icons.Outlined.BarChart + Icons.Outlined.BarChart, ) SortType.TopSixMonths -> SortData( R.string.sorttype_topsixmonths, R.string.dialogs_top_six_month, - Icons.Outlined.BarChart + Icons.Outlined.BarChart, ) SortType.TopNineMonths -> SortData( R.string.sorttype_topninemonths, R.string.dialogs_top_nine_month, - Icons.Outlined.BarChart + Icons.Outlined.BarChart, ) SortType.Scaled -> SortData(R.string.sorttype_scaled, R.string.sorttype_scaled, Icons.Outlined.Scale) } - /** * Returns localized Strings for UserTab Enum */ diff --git a/app/src/main/java/com/jerboa/datatypes/SampleData.kt b/app/src/main/java/com/jerboa/datatypes/SampleData.kt index 37d7a0389..6efa51020 100644 --- a/app/src/main/java/com/jerboa/datatypes/SampleData.kt +++ b/app/src/main/java/com/jerboa/datatypes/SampleData.kt @@ -158,7 +158,7 @@ val samplePerson = updated = "2021-10-11T07:14:53.548707", actor_id = "https://lemmy.ml/u/homeless", bio = - "This is my bio.\n\nI like trucks, trains, and geese. This is *one* longer line " + + "This is my bio.\n\nI like trucks, trains, and geese. This is *one* longer line " + "that I have in here. But I'm not sure blah blah blah\n\nI have " + "**tres ojos**.", local = true, @@ -311,7 +311,7 @@ val sampleComment = creator_id = 56450, post_id = 139549, content = - "This *looks* really cool and similar to Joplin. **Having issues** getting LaTeX to" + + "This *looks* really cool and similar to Joplin. **Having issues** getting LaTeX to" + " " + "work" + ".\n\nIts kind of a long comment\n\nbut I don't want...", diff --git a/app/src/main/java/com/jerboa/datatypes/Utils.kt b/app/src/main/java/com/jerboa/datatypes/Utils.kt index ea06bc8d2..bc3a00771 100644 --- a/app/src/main/java/com/jerboa/datatypes/Utils.kt +++ b/app/src/main/java/com/jerboa/datatypes/Utils.kt @@ -2,5 +2,4 @@ package com.jerboa.datatypes import it.vercruysse.lemmyapi.v0x19.datatypes.Person - fun Person.getDisplayName(): String = this.display_name ?: this.name diff --git a/app/src/main/java/com/jerboa/model/InboxViewModel.kt b/app/src/main/java/com/jerboa/model/InboxViewModel.kt index 68022f026..c19656e50 100644 --- a/app/src/main/java/com/jerboa/model/InboxViewModel.kt +++ b/app/src/main/java/com/jerboa/model/InboxViewModel.kt @@ -19,8 +19,6 @@ import com.jerboa.findAndUpdateMention import com.jerboa.findAndUpdatePersonMention import com.jerboa.findAndUpdatePrivateMessage import com.jerboa.getDeduplicateMerge -import com.jerboa.showBlockCommunityToast -import com.jerboa.showBlockPersonToast import com.jerboa.util.blockPerson import it.vercruysse.lemmyapi.dto.CommentSortType import it.vercruysse.lemmyapi.v0x19.datatypes.* @@ -56,7 +54,6 @@ class InboxViewModel(account: Account, siteViewModel: SiteViewModel) : ViewModel private var markAllAsReadRes: ApiState by mutableStateOf(ApiState.Empty) - private var blockPersonRes: ApiState by mutableStateOf(ApiState.Empty) @@ -438,7 +435,7 @@ class InboxViewModel(account: Account, siteViewModel: SiteViewModel) : ViewModel fun blockPerson( form: BlockPerson, ctx: Context, - ) = blockPerson(viewModelScope, form, ctx) + ) = blockPerson(viewModelScope, form, ctx) fun markAllAsRead(onComplete: () -> Unit) { viewModelScope.launch { diff --git a/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt b/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt index 13214b28c..f2907caf7 100644 --- a/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt +++ b/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt @@ -1,6 +1,5 @@ package com.jerboa.model -import android.content.Context import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf @@ -18,8 +17,6 @@ import com.jerboa.findAndUpdateComment import com.jerboa.findAndUpdatePost import com.jerboa.getDeduplicateMerge import com.jerboa.model.helper.CommentsHelper -import com.jerboa.showBlockCommunityToast -import com.jerboa.showBlockPersonToast import it.vercruysse.lemmyapi.dto.SortType import it.vercruysse.lemmyapi.v0x19.datatypes.* import kotlinx.coroutines.launch @@ -190,7 +187,7 @@ class PersonProfileViewModel(personArg: Either, savedMode: Boo } } - override fun updateComment(commentView: CommentView) { + override fun updateComment(commentView: CommentView) { when (val existing = personDetailsRes) { is ApiState.Success -> { val newComments = diff --git a/app/src/main/java/com/jerboa/model/PostViewModel.kt b/app/src/main/java/com/jerboa/model/PostViewModel.kt index 47218d755..fcc9027b9 100644 --- a/app/src/main/java/com/jerboa/model/PostViewModel.kt +++ b/app/src/main/java/com/jerboa/model/PostViewModel.kt @@ -1,6 +1,5 @@ package com.jerboa.model -import android.content.Context import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf @@ -17,7 +16,6 @@ import com.jerboa.api.toApiState import com.jerboa.appendData import com.jerboa.findAndUpdateComment import com.jerboa.model.helper.CommentsHelper -import com.jerboa.showBlockPersonToast import it.vercruysse.lemmyapi.dto.CommentSortType import it.vercruysse.lemmyapi.dto.ListingType import it.vercruysse.lemmyapi.v0x19.datatypes.* @@ -41,6 +39,7 @@ class PostViewModel(val id: Either) : ViewModel(), CommentsHe val commentsWithToggledActionBar = mutableStateListOf() override val scope: CoroutineScope = viewModelScope + init { this.getData() } @@ -174,7 +173,7 @@ class PostViewModel(val id: Either) : ViewModel(), CommentsHe existing.data.comments, commentView, ) - commentsRes = ApiState.Success(existing.data.copy(comments = newComments)) + commentsRes = ApiState.Success(existing.data.copy(comments = newComments)) } else -> {} diff --git a/app/src/main/java/com/jerboa/model/SearchListViewModel.kt b/app/src/main/java/com/jerboa/model/SearchListViewModel.kt index 056656b16..5bf4822f9 100644 --- a/app/src/main/java/com/jerboa/model/SearchListViewModel.kt +++ b/app/src/main/java/com/jerboa/model/SearchListViewModel.kt @@ -1,6 +1,5 @@ package com.jerboa.model - import android.content.Context import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -28,15 +27,14 @@ import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityView import it.vercruysse.lemmyapi.v0x19.datatypes.Search import it.vercruysse.lemmyapi.v0x19.datatypes.SearchResponse import kotlinx.collections.immutable.ImmutableList -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch class SearchListViewModel( - communities: ImmutableList, selectCommunityMode: Boolean + communities: ImmutableList, + selectCommunityMode: Boolean, ) : ViewModel(), CommentsHelper { - private var fetchSearchJob: Job? = null var q by mutableStateOf("") @@ -50,6 +48,7 @@ class SearchListViewModel( var page by mutableIntStateOf(1) override val scope = viewModelScope + override fun updateComment(commentView: CommentView) { when (val existing = searchRes) { is ApiState.Success -> { @@ -76,10 +75,11 @@ class SearchListViewModel( fun updateSearch() { fetchSearchJob?.cancel() - fetchSearchJob = viewModelScope.launch { - delay(DEBOUNCE_DELAY) - search() - } + fetchSearchJob = + viewModelScope.launch { + delay(DEBOUNCE_DELAY) + search() + } } fun onSearchChange(q: String) { @@ -105,37 +105,39 @@ class SearchListViewModel( ) } - private fun setCommunityListFromFollowed(myFollows: ImmutableList) { // A hack to convert communityFollowerView into CommunityView - val followsIntoCommunityViews = myFollows.map { cfv -> - CommunityView( - community = cfv.community, - subscribed = SubscribedType.Subscribed, - blocked = false, - counts = CommunityAggregates( - community_id = cfv.community.id, - subscribers = 0, - posts = 0, - comments = 0, - published = "", - users_active_day = 0, - users_active_week = 0, - users_active_month = 0, - users_active_half_year = 0, + val followsIntoCommunityViews = + myFollows.map { cfv -> + CommunityView( + community = cfv.community, + subscribed = SubscribedType.Subscribed, + blocked = false, + counts = + CommunityAggregates( + community_id = cfv.community.id, + subscribers = 0, + posts = 0, + comments = 0, + published = "", + users_active_day = 0, + users_active_week = 0, + users_active_month = 0, + users_active_half_year = 0, + ), + ) + } + + searchRes = + ApiState.Success( + SearchResponse( + type_ = SearchType.Communities, + communities = followsIntoCommunityViews, + comments = emptyList(), + posts = emptyList(), + users = emptyList(), ), ) - } - - searchRes = ApiState.Success( - SearchResponse( - type_ = SearchType.Communities, - communities = followsIntoCommunityViews, - comments = emptyList(), - posts = emptyList(), - users = emptyList(), - ), - ) } fun searchNextPage(ctx: Context) { diff --git a/app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt b/app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt index 3d836fab0..54cbe8f8c 100644 --- a/app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt +++ b/app/src/main/java/com/jerboa/model/helper/CommentsHelper.kt @@ -1,7 +1,6 @@ package com.jerboa.model.helper import android.content.Context -import androidx.lifecycle.viewModelScope import com.jerboa.api.API import com.jerboa.api.toApiState import com.jerboa.showBlockPersonToast @@ -16,9 +15,10 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext interface CommentsHelper { - val scope: CoroutineScope + fun updateComment(commentView: CommentView) + fun likeComment(form: CreateCommentLike) { scope.launch { val res = API.getInstance().createCommentLike(form) @@ -56,4 +56,4 @@ interface CommentsHelper { } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt b/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt index 69b1cd785..d999cc78f 100644 --- a/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt +++ b/app/src/main/java/com/jerboa/ui/components/common/DropdownMenu.kt @@ -8,12 +8,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.BarChart import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExposedDropdownMenuBox -import androidx.compose.material3.ExposedDropdownMenuDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt b/app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt index ef2b68358..46988e1b2 100644 --- a/app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt +++ b/app/src/main/java/com/jerboa/ui/components/common/FormComponents.kt @@ -28,18 +28,18 @@ fun ClickableOutlinedTextField( onValueChange = {}, trailingIcon = trailingIcon, modifier = Modifier.clickable { onClick() }, - colors = OutlinedTextFieldDefaults.colors( - disabledTextColor = MaterialTheme.colorScheme.onSurface, - disabledBorderColor = MaterialTheme.colorScheme.outline, - disabledLeadingIconColor = MaterialTheme.colorScheme.onSurfaceVariant, - disabledTrailingIconColor = MaterialTheme.colorScheme.onSurfaceVariant, - disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant, - disabledPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant, - ) + colors = + OutlinedTextFieldDefaults.colors( + disabledTextColor = MaterialTheme.colorScheme.onSurface, + disabledBorderColor = MaterialTheme.colorScheme.outline, + disabledLeadingIconColor = MaterialTheme.colorScheme.onSurfaceVariant, + disabledTrailingIconColor = MaterialTheme.colorScheme.onSurfaceVariant, + disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant, + disabledPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant, + ), ) } - @OptIn(ExperimentalMaterial3Api::class) @Composable fun ReadOnlyDropdown( @@ -81,4 +81,3 @@ fun ReadOnlyDropdown( } } } - diff --git a/app/src/main/java/com/jerboa/ui/components/community/Community.kt b/app/src/main/java/com/jerboa/ui/components/community/Community.kt index d37b7bc43..bb92faa68 100644 --- a/app/src/main/java/com/jerboa/ui/components/community/Community.kt +++ b/app/src/main/java/com/jerboa/ui/components/community/Community.kt @@ -172,7 +172,7 @@ fun CommunityHeader( }) { Icon( Icons.Outlined.Sort, - contentDescription = stringResource(R.string.community_sortBy), + contentDescription = stringResource(R.string.selectSort), ) } diff --git a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt index d9727609a..2b416f0df 100644 --- a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt @@ -50,10 +50,10 @@ import com.jerboa.model.SiteViewModel import com.jerboa.ui.components.common.BottomAppBarAll import com.jerboa.ui.components.common.JerboaSnackbarHost import com.jerboa.ui.components.common.getCurrentAccount -import com.jerboa.ui.components.search.SearchActivity import com.jerboa.ui.components.drawer.MainDrawer import com.jerboa.ui.components.inbox.InboxActivity import com.jerboa.ui.components.person.PersonProfileActivity +import com.jerboa.ui.components.search.SearchActivity import kotlinx.coroutines.launch enum class NavTab( diff --git a/app/src/main/java/com/jerboa/ui/components/person/PersonProfile.kt b/app/src/main/java/com/jerboa/ui/components/person/PersonProfile.kt index ac96d58bb..8396bc3fa 100644 --- a/app/src/main/java/com/jerboa/ui/components/person/PersonProfile.kt +++ b/app/src/main/java/com/jerboa/ui/components/person/PersonProfile.kt @@ -200,7 +200,7 @@ fun PersonProfileHeader( }) { Icon( Icons.Outlined.Sort, - contentDescription = stringResource(R.string.community_sortBy), + contentDescription = stringResource(R.string.selectSort), ) } diff --git a/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt b/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt index 57f8ceab2..639a62d63 100644 --- a/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt @@ -179,11 +179,11 @@ fun PersonProfileActivity( PersonProfileHeader( scrollBehavior = scrollBehavior, personName = - if (savedMode) { - ctx.getString(R.string.bookmarks_activity_saved) - } else { - person.name - }, + if (savedMode) { + ctx.getString(R.string.bookmarks_activity_saved) + } else { + person.name + }, myProfile = account.id == person.id, selectedSortType = personProfileViewModel.sortType, onClickSortType = { sortType -> @@ -387,9 +387,9 @@ fun UserTabs( LazyColumn( state = listState, modifier = - Modifier - .fillMaxSize() - .simpleVerticalScrollbar(listState), + Modifier + .fillMaxSize() + .simpleVerticalScrollbar(listState), ) { item(contentType = "topSection") { PersonProfileTopSection( @@ -433,9 +433,9 @@ fun UserTabs( UserTab.Posts.ordinal -> { Box( modifier = - Modifier - .pullRefresh(pullRefreshState) - .fillMaxSize(), + Modifier + .pullRefresh(pullRefreshState) + .fillMaxSize(), ) { JerboaPullRefreshIndicator( personProfileViewModel.personDetailsRes.isRefreshing(), @@ -467,10 +467,10 @@ fun UserTabs( CreatePostLike( post_id = pv.post.id, score = - newVote( - pv.my_vote, - VoteType.Upvote, - ), + newVote( + pv.my_vote, + VoteType.Upvote, + ), ), ) } @@ -487,10 +487,10 @@ fun UserTabs( CreatePostLike( post_id = pv.post.id, score = - newVote( - pv.my_vote, - VoteType.Downvote, - ), + newVote( + pv.my_vote, + VoteType.Downvote, + ), ), ) } diff --git a/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt b/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt index b2aeb0911..4fb76cc85 100644 --- a/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/post/create/CreatePostActivity.kt @@ -35,9 +35,9 @@ import com.jerboa.padUrlWithHttps import com.jerboa.ui.components.common.ActionTopBar import com.jerboa.ui.components.common.LoadingBar import com.jerboa.ui.components.common.getCurrentAccount -import com.jerboa.ui.components.search.SearchListReturn import com.jerboa.ui.components.post.composables.CreateEditPostBody import com.jerboa.ui.components.post.composables.PostCommunitySelector +import com.jerboa.ui.components.search.SearchListReturn import com.jerboa.validatePostName import com.jerboa.validateUrl import it.vercruysse.lemmyapi.v0x19.datatypes.Community diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt index a4bc3639d..958cc7e75 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt @@ -127,7 +127,6 @@ fun SearchActivity( }, ) } - } when (val communitiesRes = searchListViewModel.searchRes) { @@ -137,7 +136,6 @@ fun SearchActivity( } is ApiState.Success -> { - val listState = rememberLazyListState() val endOfListReached by remember { @@ -154,7 +152,6 @@ fun SearchActivity( val nodes by remember { mutableStateOf(commentsToFlatNodes(communitiesRes.data.comments)) } - // Holds the un-expanded comment ids val unExpandedComments = remember { mutableStateListOf() } val commentsWithToggledActionBar = remember { mutableStateListOf() } @@ -177,8 +174,6 @@ fun SearchActivity( val showActionBarByDefault = true - - LazyColumn( state = listState, modifier = Modifier.simpleVerticalScrollbar(listState), @@ -343,15 +338,11 @@ fun SearchActivity( blurNSFW = blurNSFW, ) } - - } else -> {} } } - - }, ) } diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt index 54d3081e3..22714ede6 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview import com.jerboa.R import com.jerboa.ui.components.community.CommunityLinkLarger -import com.jerboa.ui.components.community.CommunityLinkLargerWithUserCount import it.vercruysse.lemmyapi.v0x19.datatypes.* @OptIn(ExperimentalMaterial3Api::class) @@ -62,7 +61,7 @@ fun SearchListHeader( ) } -fun LazyListScope. searchCommunityListings( +fun LazyListScope.searchCommunityListings( communities: List, onClickCommunity: (community: Community) -> Unit, blurNSFW: Int, @@ -77,8 +76,12 @@ fun LazyListScope. searchCommunityListings( showDefaultIcon = true, blurNSFW = blurNSFW, // A hack for the community follower views that were coerced into community views without counts - usersPerMonth = if (item.counts.users_active_month == 0) null - else item.counts.users_active_month, + usersPerMonth = + if (item.counts.users_active_month == 0) { + null + } else { + item.counts.users_active_month + }, ) } } @@ -109,15 +112,16 @@ fun TopBarSearchField( } }, singleLine = true, - colors = TextFieldDefaults.colors( - focusedContainerColor = Color.Transparent, - unfocusedContainerColor = Color.Transparent, - disabledContainerColor = Color.Transparent, - errorContainerColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - ), + colors = + TextFieldDefaults.colors( + focusedContainerColor = Color.Transparent, + unfocusedContainerColor = Color.Transparent, + disabledContainerColor = Color.Transparent, + errorContainerColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + ), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), ) } diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt index 695c54f37..48f1948ad 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchListPersonItem.kt @@ -23,15 +23,11 @@ import com.jerboa.personNameShown import com.jerboa.ui.components.common.CircularIcon import com.jerboa.ui.components.person.CommentsAndPosts import com.jerboa.ui.theme.DRAWER_ITEM_SPACING -import com.jerboa.ui.theme.ICON_SIZE -import com.jerboa.ui.theme.ICON_THUMBNAIL_SIZE import com.jerboa.ui.theme.LARGER_ICON_THUMBNAIL_SIZE import com.jerboa.ui.theme.LARGE_PADDING import com.jerboa.ui.theme.LINK_ICON_SIZE -import com.jerboa.ui.theme.SMALL_PADDING import it.vercruysse.lemmyapi.v0x19.datatypes.PersonView - @Composable fun SearchListPersonItem( personView: PersonView, @@ -43,10 +39,11 @@ fun SearchListPersonItem( Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(spacing), - modifier = Modifier - .clickable { onClickPerson(personView) } - .padding(LARGE_PADDING) - .fillMaxWidth(), + modifier = + Modifier + .clickable { onClickPerson(personView) } + .padding(LARGE_PADDING) + .fillMaxWidth(), ) { val avatar = personView.person.avatar @@ -88,4 +85,4 @@ fun PersonName( overflow = overflow, maxLines = 1, ) -} \ No newline at end of file +} diff --git a/app/src/main/java/com/jerboa/ui/components/search/searchListings.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchListings.kt similarity index 73% rename from app/src/main/java/com/jerboa/ui/components/search/searchListings.kt rename to app/src/main/java/com/jerboa/ui/components/search/SearchListings.kt index 04edc68e2..b9884b503 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/searchListings.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchListings.kt @@ -4,7 +4,10 @@ import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items import it.vercruysse.lemmyapi.v0x19.datatypes.PersonView -fun LazyListScope.searchPersonListings(personViews: List, onPersonClick: (PersonView) -> Unit){ +fun LazyListScope.searchPersonListings( + personViews: List, + onPersonClick: (PersonView) -> Unit, +) { items(personViews) { personView -> SearchListPersonItem(personView = personView, onClickPerson = onPersonClick) } diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt index 041a67c7c..b14331b40 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt @@ -1,19 +1,13 @@ package com.jerboa.ui.components.search -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding -import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.ExposedDropdownMenuDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -23,6 +17,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import com.jerboa.R import com.jerboa.datatypes.data import com.jerboa.datatypes.getLocalizedListingTypeName import com.jerboa.ui.components.common.ClickableOutlinedTextField @@ -32,13 +27,15 @@ import it.vercruysse.lemmyapi.dto.ListingType import it.vercruysse.lemmyapi.dto.SearchType import it.vercruysse.lemmyapi.dto.SortType - @OptIn(ExperimentalMaterial3Api::class) @Composable fun SearchParametersField( - currentSort: SortType, setCurrentSort: (SortType) -> Unit, - currentSearchType: SearchType, setCurrentSearchType: (SearchType) -> Unit, - currentListing: ListingType, setCurrentListing: (ListingType) -> Unit + currentSort: SortType, + setCurrentSort: (SortType) -> Unit, + currentSearchType: SearchType, + setCurrentSearchType: (SearchType) -> Unit, + currentListing: ListingType, + setCurrentListing: (ListingType) -> Unit, ) { val ctx = LocalContext.current @@ -47,15 +44,13 @@ fun SearchParametersField( var expandedSort by rememberSaveable { mutableStateOf(false) } Column( - modifier = Modifier - .padding(16.dp, 16.dp), + modifier = Modifier.padding(16.dp, 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Box { ClickableOutlinedTextField( value = stringResource(currentSort.data.shortForm), - label = { Text("Sort By") }, + label = { Text(stringResource(R.string.selectSort)) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expandedSort) }, onClick = { expandedSort = true }, ) @@ -68,7 +63,7 @@ fun SearchParametersField( setCurrentSort(it) }, selectedSortType = currentSort, - fixedWidth = OutlinedTextFieldDefaults.MinWidth + fixedWidth = OutlinedTextFieldDefaults.MinWidth, ) } @@ -78,7 +73,7 @@ fun SearchParametersField( states = SearchType.entries, state = currentSearchType, setState = setCurrentSearchType, - label = "Search In", // TODO + label = stringResource(R.string.search_in), stringTransform = { it.name }, ) ReadOnlyDropdown( @@ -87,8 +82,8 @@ fun SearchParametersField( states = ListingType.entries, state = currentListing, setState = setCurrentListing, - label = "Limit To", // TODO + label = stringResource(R.string.limit_to), stringTransform = { getLocalizedListingTypeName(ctx, it) }, ) } -} \ No newline at end of file +} diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index cb8b0d812..278957180 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -82,7 +82,6 @@ %1$s مستخدم \ شهر ابحث… انتظر الإذن - رتِّب حسب اشترك %1$s مستخدم \ شهر سجلَّات التعطُّل diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index e255502b1..cc8dc90ae 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -80,7 +80,6 @@ %1$s istifadəçi / ay Axtar… Gözlə - Çeşidlə Abunə ol %1$s istifadəçi / ay Çökmə Jurnalları diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 6da5f4959..95f679aa5 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -82,7 +82,6 @@ %1$s потребители / месец Търсене… В очакване - Сортиране по Абониране %1$s потребители / месец Дневник на сривовете diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 359730dfc..63818a098 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -175,7 +175,6 @@ Vis flere muligheder Gem redigeret kommentar Send svar - Sorter efter Opret indlæg Fællesskabets ikon Indsend diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b49627f69..ae8e1e9c7 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -183,7 +183,6 @@ Zeige mehr Optionen Kommentarbearbeitung speichern Antwort senden - Sortieren nach Beitrag erstellen Community Symbol Abschicken diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 5393ba35c..0bc4e3793 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -80,7 +80,6 @@ %1$s χρήστες / μήνα Αναζήτηση… Εκκρεμεί - Ταξινόμηση κατά Εγγραφή %1$s χρήστες / μήνα Επιλογή κοινότητας από τη λίστα diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index ec8e33f9a..3caa4ad35 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -193,7 +193,6 @@ Mostrar más opciones Guardar ediciones del comentario Enviar respuesta - Ordenar por La versión del servidor (%1$s) se encuentra por debajo de la versión mínima soportada (%2$s). La versión del servidor (%1$s) es muy baja. Crear post diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index d585ac372..fa8cec389 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -191,7 +191,6 @@ Plus d’options Enregistrer les modifications Envoyer la réponse - Trier par La version du serveur (%1$s) est inférieure à la version minimale prise en charge (%2$s). Veuillez informer l’administrateur de l’instance et vous connecter à une autre instance, ou vous déconnecter et utiliser l’instance par défaut. Créer publication Icône de la communauté diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 4ac21a5f1..85fc54156 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -80,7 +80,6 @@ %1$s utenti / mese Cerca… In attesa - Ordina per Partecipa %1$s utenti / mese Seleziona comunità dalla lista diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 93040190d..87c881290 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -176,7 +176,6 @@ 追加オプションを表示 コメント編集を保存 返信を送る - 並び替え 投稿を作成 コミュニティアイコン 確定 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index f319f8920..ada6bfbf2 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -80,7 +80,6 @@ %1$s 사용자 / 월 검색… 보류 중 - 정렬 구독 %1$s 사용자 / 월 크래시 기록 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 00c645471..e5757d44d 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -65,7 +65,6 @@ %1$s gebruikers / maand Community icoon Lid geworden - Sorteer op Abonneren In behandeling Bewaar reactie diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index cee5743a9..9e6cdcee2 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -81,8 +81,7 @@ %1$s brukarar/månad Søk … Ventar - Sorter etter - Abonner + Abonner %1$s brukarar/månad Krasjloggar Alle krasjloggar vart sletta diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 02ef2480d..ad989eceb 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -176,7 +176,6 @@ Pokaż więcej opcji Zapisz edytowany komentarz Wyślij odpowiedź - Sortuj po Stwórz post Ikonka Społeczności Prześlij diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 26f8d6964..a9f597176 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -24,7 +24,6 @@ %1$s пользователей / месяц Поиск… В ожидании - Отсортировать по Подписаться %1$s пользователей / месяц Журналы сбоев diff --git a/app/src/main/res/values-se/strings.xml b/app/src/main/res/values-se/strings.xml index 3cd21f800..664b7e0e4 100644 --- a/app/src/main/res/values-se/strings.xml +++ b/app/src/main/res/values-se/strings.xml @@ -175,7 +175,6 @@ Visa fler alternativ Spara redigerad kommentar Skicka svar - Sortera efter Skapa inlägg Gemenskapens profilbild Skicka in diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 16b9ced8b..c65042d45 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -81,7 +81,6 @@ %1$s користувачів за місяць Що ви шукаєте? Очікує на розгляд - Впорядкувати за Передплатити %1$s користувачів за місяць Обрати спільноту з переліку diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 338f563e4..42f9f74b9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -82,7 +82,6 @@ %1$s users / month Search… Pending - Sort by Subscribe %1$s users / month Crash Logs @@ -403,4 +402,6 @@ Failed to parse datetime There is no record of this comment The version (%s) is not supported + Search in + Limit to From 36d69526370d7e95818d1e3f891561611ca0b3ed Mon Sep 17 00:00:00 2001 From: "maarten.vercruysse" Date: Tue, 26 Dec 2023 00:27:43 +0100 Subject: [PATCH 3/4] Add posts functionality --- app/src/main/java/com/jerboa/MainActivity.kt | 2 +- app/src/main/java/com/jerboa/Utils.kt | 7 +- .../java/com/jerboa/model/HomeViewModel.kt | 7 - .../jerboa/model/PersonProfileViewModel.kt | 89 +++-------- .../java/com/jerboa/model/PostViewModel.kt | 54 +------ .../java/com/jerboa/model/PostsViewModel.kt | 34 +---- .../com/jerboa/model/SearchListViewModel.kt | 25 +++- .../com/jerboa/model/helper/PostsHelper.kt | 39 +++++ .../ui/components/home/BottomNavActivity.kt | 2 +- .../ui/components/search/SearchActivity.kt | 141 +++++++++++++++++- .../jerboa/ui/components/search/SearchList.kt | 6 +- .../ui/components/search/SearchListings.kt | 2 + .../search/SearchParametersField.kt | 2 +- 13 files changed, 235 insertions(+), 175 deletions(-) create mode 100644 app/src/main/java/com/jerboa/model/helper/PostsHelper.kt diff --git a/app/src/main/java/com/jerboa/MainActivity.kt b/app/src/main/java/com/jerboa/MainActivity.kt index b6f9941ac..cf3d28b14 100644 --- a/app/src/main/java/com/jerboa/MainActivity.kt +++ b/app/src/main/java/com/jerboa/MainActivity.kt @@ -368,7 +368,7 @@ class MainActivity : AppCompatActivity() { SearchActivity( appState = appState, selectCommunityMode = args.select, - blurNSFW = appSettings.blurNSFW, + appSettings = appSettings, drawerState = drawerState, followList = siteViewModel.getFollowList(), accountViewModel = accountViewModel, diff --git a/app/src/main/java/com/jerboa/Utils.kt b/app/src/main/java/com/jerboa/Utils.kt index cebb2dda5..aad5e252a 100644 --- a/app/src/main/java/com/jerboa/Utils.kt +++ b/app/src/main/java/com/jerboa/Utils.kt @@ -1234,10 +1234,9 @@ fun findAndUpdatePost( posts: List, updatedPostView: PostView, ): List { - val foundIndex = - posts.indexOfFirst { - it.post.id == updatedPostView.post.id - } + val foundIndex = posts.indexOfFirst { + it.post.id == updatedPostView.post.id + } return if (foundIndex != -1) { val mutable = posts.toMutableList() mutable[foundIndex] = updatedPostView diff --git a/app/src/main/java/com/jerboa/model/HomeViewModel.kt b/app/src/main/java/com/jerboa/model/HomeViewModel.kt index 56c41246c..b9259da66 100644 --- a/app/src/main/java/com/jerboa/model/HomeViewModel.kt +++ b/app/src/main/java/com/jerboa/model/HomeViewModel.kt @@ -3,26 +3,19 @@ package com.jerboa.model import android.util.Log import androidx.compose.foundation.lazy.LazyListState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.asFlow import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory -import com.jerboa.api.ApiState import com.jerboa.db.entity.AnonAccount import com.jerboa.db.repository.AccountRepository import com.jerboa.jerboaApplication import com.jerboa.toEnumSafe -import it.vercruysse.lemmyapi.v0x19.datatypes.PostResponse import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch class HomeViewModel(private val accountRepository: AccountRepository) : PostsViewModel() { - private var likePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var savePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var deletePostRes: ApiState by mutableStateOf(ApiState.Empty) - val lazyListState = LazyListState() init { diff --git a/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt b/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt index f2907caf7..b3f3f83aa 100644 --- a/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt +++ b/app/src/main/java/com/jerboa/model/PersonProfileViewModel.kt @@ -17,18 +17,18 @@ import com.jerboa.findAndUpdateComment import com.jerboa.findAndUpdatePost import com.jerboa.getDeduplicateMerge import com.jerboa.model.helper.CommentsHelper +import com.jerboa.model.helper.PostsHelper import it.vercruysse.lemmyapi.dto.SortType import it.vercruysse.lemmyapi.v0x19.datatypes.* import kotlinx.coroutines.launch -class PersonProfileViewModel(personArg: Either, savedMode: Boolean) : ViewModel(), CommentsHelper { +class PersonProfileViewModel( + personArg: Either, + savedMode: Boolean, +) : ViewModel(), CommentsHelper, PostsHelper { var personDetailsRes: ApiState by mutableStateOf(ApiState.Empty) private set - private var likePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var savePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var deletePostRes: ApiState by mutableStateOf(ApiState.Empty) - override val scope = viewModelScope private var markPostRes: ApiState by mutableStateOf(ApiState.Empty) @@ -89,12 +89,11 @@ class PersonProfileViewModel(personArg: Either, savedMode: Boo fun appendData(profileId: PersonId) { viewModelScope.launch { val oldRes = personDetailsRes - personDetailsRes = - when (oldRes) { - is ApiState.Appending -> return@launch - is ApiState.Holder -> ApiState.Appending(oldRes.data) - else -> return@launch - } + personDetailsRes = when (oldRes) { + is ApiState.Appending -> return@launch + is ApiState.Holder -> ApiState.Appending(oldRes.data) + else -> return@launch + } nextPage() val form = @@ -131,56 +130,11 @@ class PersonProfileViewModel(personArg: Either, savedMode: Boo } } - fun likePost(form: CreatePostLike) { - viewModelScope.launch { - likePostRes = ApiState.Loading - likePostRes = API.getInstance().createPostLike(form).toApiState() - - when (val likeRes = likePostRes) { - is ApiState.Success -> { - updatePost(likeRes.data.post_view) - } - - else -> {} - } - } - } - - fun savePost(form: SavePost) { - viewModelScope.launch { - savePostRes = ApiState.Loading - savePostRes = API.getInstance().savePost(form).toApiState() - when (val saveRes = savePostRes) { - is ApiState.Success -> { - updatePost(saveRes.data.post_view) - } - - else -> {} - } - } - } - - fun deletePost(form: DeletePost) { - viewModelScope.launch { - deletePostRes = ApiState.Loading - deletePostRes = API.getInstance().deletePost(form).toApiState() - when (val deletePost = deletePostRes) { - is ApiState.Success -> { - updatePost(deletePost.data.post_view) - } - - else -> {} - } - } - } - - fun updatePost(postView: PostView) { + override fun updatePost(postView: PostView) { when (val existing = personDetailsRes) { is ApiState.Success -> { - val newPosts = - findAndUpdatePost(existing.data.posts, postView) - val newRes = ApiState.Success(existing.data.copy(posts = newPosts)) - personDetailsRes = newRes + val newPosts = findAndUpdatePost(existing.data.posts, postView) + personDetailsRes = ApiState.Success(existing.data.copy(posts = newPosts)) } else -> {} @@ -190,14 +144,11 @@ class PersonProfileViewModel(personArg: Either, savedMode: Boo override fun updateComment(commentView: CommentView) { when (val existing = personDetailsRes) { is ApiState.Success -> { - val newComments = - findAndUpdateComment( - existing.data.comments, - commentView, - ) - val newRes = - ApiState.Success(existing.data.copy(comments = newComments)) - personDetailsRes = newRes + val newComments = findAndUpdateComment( + existing.data.comments, + commentView, + ) + personDetailsRes = ApiState.Success(existing.data.copy(comments = newComments)) } else -> {} @@ -209,9 +160,7 @@ class PersonProfileViewModel(personArg: Either, savedMode: Boo is ApiState.Success -> { val mutable = existing.data.comments.toMutableList() mutable.add(0, commentView) - val newRes = - ApiState.Success(existing.data.copy(comments = mutable.toList())) - personDetailsRes = newRes + personDetailsRes = ApiState.Success(existing.data.copy(comments = mutable.toList())) } else -> {} diff --git a/app/src/main/java/com/jerboa/model/PostViewModel.kt b/app/src/main/java/com/jerboa/model/PostViewModel.kt index fcc9027b9..710fa1492 100644 --- a/app/src/main/java/com/jerboa/model/PostViewModel.kt +++ b/app/src/main/java/com/jerboa/model/PostViewModel.kt @@ -16,13 +16,16 @@ import com.jerboa.api.toApiState import com.jerboa.appendData import com.jerboa.findAndUpdateComment import com.jerboa.model.helper.CommentsHelper +import com.jerboa.model.helper.PostsHelper import it.vercruysse.lemmyapi.dto.CommentSortType import it.vercruysse.lemmyapi.dto.ListingType import it.vercruysse.lemmyapi.v0x19.datatypes.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -class PostViewModel(val id: Either) : ViewModel(), CommentsHelper { +class PostViewModel( + val id: Either, +) : ViewModel(), CommentsHelper, PostsHelper { var postRes: ApiState by mutableStateOf(ApiState.Empty) private set @@ -31,10 +34,6 @@ class PostViewModel(val id: Either) : ViewModel(), CommentsHe var sortType by mutableStateOf(CommentSortType.Hot) private set - private var likePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var savePostRes: ApiState by mutableStateOf(ApiState.Empty) - private var deletePostRes: ApiState by mutableStateOf(ApiState.Empty) - val unExpandedComments = mutableStateListOf() val commentsWithToggledActionBar = mutableStateListOf() @@ -122,49 +121,6 @@ class PostViewModel(val id: Either) : ViewModel(), CommentsHe } } - fun likePost(form: CreatePostLike) { - viewModelScope.launch { - likePostRes = ApiState.Loading - likePostRes = API.getInstance().createPostLike(form).toApiState() - - when (val likeRes = likePostRes) { - is ApiState.Success -> { - updatePost(likeRes.data.post_view) - } - - else -> {} - } - } - } - - fun savePost(form: SavePost) { - viewModelScope.launch { - savePostRes = ApiState.Loading - savePostRes = API.getInstance().savePost(form).toApiState() - when (val saveRes = savePostRes) { - is ApiState.Success -> { - updatePost(saveRes.data.post_view) - } - - else -> {} - } - } - } - - fun deletePost(form: DeletePost) { - viewModelScope.launch { - deletePostRes = ApiState.Loading - deletePostRes = API.getInstance().deletePost(form).toApiState() - when (val deletePost = deletePostRes) { - is ApiState.Success -> { - updatePost(deletePost.data.post_view) - } - - else -> {} - } - } - } - override fun updateComment(commentView: CommentView) { when (val existing = commentsRes) { is ApiState.Success -> { @@ -194,7 +150,7 @@ class PostViewModel(val id: Either) : ViewModel(), CommentsHe } } - fun updatePost(postView: PostView) { + override fun updatePost(postView: PostView) { when (val existing = postRes) { is ApiState.Success -> { val newRes = ApiState.Success(existing.data.copy(post_view = postView)) diff --git a/app/src/main/java/com/jerboa/model/PostsViewModel.kt b/app/src/main/java/com/jerboa/model/PostsViewModel.kt index bd8034ad1..c0d452a96 100644 --- a/app/src/main/java/com/jerboa/model/PostsViewModel.kt +++ b/app/src/main/java/com/jerboa/model/PostsViewModel.kt @@ -12,19 +12,17 @@ import com.jerboa.api.ApiState import com.jerboa.api.toApiState import com.jerboa.findAndUpdatePost import com.jerboa.mergePosts +import com.jerboa.model.helper.PostsHelper import it.vercruysse.lemmyapi.dto.ListingType import it.vercruysse.lemmyapi.dto.SortType -import it.vercruysse.lemmyapi.v0x19.datatypes.CreatePostLike -import it.vercruysse.lemmyapi.v0x19.datatypes.DeletePost import it.vercruysse.lemmyapi.v0x19.datatypes.GetPosts import it.vercruysse.lemmyapi.v0x19.datatypes.GetPostsResponse import it.vercruysse.lemmyapi.v0x19.datatypes.MarkPostAsRead import it.vercruysse.lemmyapi.v0x19.datatypes.PaginationCursor import it.vercruysse.lemmyapi.v0x19.datatypes.PostView -import it.vercruysse.lemmyapi.v0x19.datatypes.SavePost import kotlinx.coroutines.launch -open class PostsViewModel : ViewModel() { +open class PostsViewModel : ViewModel(), PostsHelper { var postsRes: ApiState by mutableStateOf(ApiState.Empty) private set private var page by mutableIntStateOf(1) @@ -35,6 +33,8 @@ open class PostsViewModel : ViewModel() { var listingType by mutableStateOf(ListingType.Local) private set + override val scope = viewModelScope + protected fun nextPage() { page += 1 } @@ -98,7 +98,7 @@ open class PostsViewModel : ViewModel() { } } - fun updatePost(postView: PostView) { + override fun updatePost(postView: PostView) { when (val existing = postsRes) { is ApiState.Success -> { val newPosts = findAndUpdatePost(existing.data.posts, postView) @@ -153,28 +153,4 @@ open class PostsViewModel : ViewModel() { fun updateListingType(listingType: ListingType) { this.listingType = listingType } - - fun likePost(form: CreatePostLike) { - viewModelScope.launch { - API.getInstance().createPostLike(form).onSuccess { - updatePost(it.post_view) - } - } - } - - fun savePost(form: SavePost) { - viewModelScope.launch { - API.getInstance().savePost(form).onSuccess { - updatePost(it.post_view) - } - } - } - - fun deletePost(form: DeletePost) { - viewModelScope.launch { - API.getInstance().deletePost(form).onSuccess { - updatePost(it.post_view) - } - } - } } diff --git a/app/src/main/java/com/jerboa/model/SearchListViewModel.kt b/app/src/main/java/com/jerboa/model/SearchListViewModel.kt index 5bf4822f9..90577aa46 100644 --- a/app/src/main/java/com/jerboa/model/SearchListViewModel.kt +++ b/app/src/main/java/com/jerboa/model/SearchListViewModel.kt @@ -14,7 +14,9 @@ import com.jerboa.api.API import com.jerboa.api.ApiState import com.jerboa.api.toApiState import com.jerboa.findAndUpdateComment +import com.jerboa.findAndUpdatePost import com.jerboa.model.helper.CommentsHelper +import com.jerboa.model.helper.PostsHelper import com.jerboa.ui.components.common.apiErrorToast import it.vercruysse.lemmyapi.dto.ListingType import it.vercruysse.lemmyapi.dto.SearchType @@ -24,6 +26,7 @@ import it.vercruysse.lemmyapi.v0x19.datatypes.CommentView import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityAggregates import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityFollowerView import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityView +import it.vercruysse.lemmyapi.v0x19.datatypes.PostView import it.vercruysse.lemmyapi.v0x19.datatypes.Search import it.vercruysse.lemmyapi.v0x19.datatypes.SearchResponse import kotlinx.collections.immutable.ImmutableList @@ -34,7 +37,7 @@ import kotlinx.coroutines.launch class SearchListViewModel( communities: ImmutableList, selectCommunityMode: Boolean, -) : ViewModel(), CommentsHelper { +) : ViewModel(), CommentsHelper, PostsHelper { private var fetchSearchJob: Job? = null var q by mutableStateOf("") @@ -43,12 +46,28 @@ class SearchListViewModel( var currentSearchType by mutableStateOf(SearchType.All) var currentListing by mutableStateOf(ListingType.All) - var currentSort by mutableStateOf(SortType.New) + var currentSort by mutableStateOf(SortType.TopAll) + var loading by mutableStateOf(false) var page by mutableIntStateOf(1) override val scope = viewModelScope + override fun updatePost(postView: PostView) { + when (val existing = searchRes) { + is ApiState.Success -> { + val newPosts = + findAndUpdatePost( + existing.data.posts, + postView, + ) + searchRes = ApiState.Success(existing.data.copy(posts = newPosts)) + } + + else -> {} + } + } + override fun updateComment(commentView: CommentView) { when (val existing = searchRes) { is ApiState.Success -> { @@ -143,6 +162,7 @@ class SearchListViewModel( fun searchNextPage(ctx: Context) { viewModelScope.launch { page++ + loading = true val res = API.getInstance().search(getForm()) res.onSuccess { @@ -165,6 +185,7 @@ class SearchListViewModel( page-- apiErrorToast(ctx, it) } + loading = false } } diff --git a/app/src/main/java/com/jerboa/model/helper/PostsHelper.kt b/app/src/main/java/com/jerboa/model/helper/PostsHelper.kt new file mode 100644 index 000000000..0952d815f --- /dev/null +++ b/app/src/main/java/com/jerboa/model/helper/PostsHelper.kt @@ -0,0 +1,39 @@ +package com.jerboa.model.helper + +import com.jerboa.api.API +import it.vercruysse.lemmyapi.v0x19.datatypes.CreatePostLike +import it.vercruysse.lemmyapi.v0x19.datatypes.DeletePost +import it.vercruysse.lemmyapi.v0x19.datatypes.PostView +import it.vercruysse.lemmyapi.v0x19.datatypes.SavePost +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +interface PostsHelper { + val scope: CoroutineScope + + fun updatePost(postView: PostView) + + fun likePost(form: CreatePostLike) { + scope.launch { + API.getInstance().createPostLike(form).onSuccess { + updatePost(it.post_view) + } + } + } + + fun savePost(form: SavePost) { + scope.launch { + API.getInstance().savePost(form).onSuccess { + updatePost(it.post_view) + } + } + } + + fun deletePost(form: DeletePost) { + scope.launch { + API.getInstance().deletePost(form).onSuccess { + updatePost(it.post_view) + } + } + } +} diff --git a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt index 2b416f0df..11dd50368 100644 --- a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt @@ -224,7 +224,7 @@ fun BottomNavActivity( appState = appState, selectCommunityMode = false, followList = siteViewModel.getFollowList(), - blurNSFW = appSettings.blurNSFW, + appSettings = appSettings, drawerState = drawerState, accountViewModel = accountViewModel, siteViewModel = siteViewModel, diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt index 958cc7e75..11d8b9a50 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt @@ -9,7 +9,9 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.Divider import androidx.compose.material3.DrawerState import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -30,9 +32,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.viewmodel.compose.viewModel import com.jerboa.JerboaAppState +import com.jerboa.PostViewMode import com.jerboa.VoteType import com.jerboa.api.ApiState import com.jerboa.commentsToFlatNodes +import com.jerboa.db.entity.AppSettings import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.isScrolledToEnd import com.jerboa.model.AccountViewModel @@ -46,11 +50,15 @@ import com.jerboa.ui.components.common.JerboaSnackbarHost import com.jerboa.ui.components.common.LoadingBar import com.jerboa.ui.components.common.getCurrentAccount import com.jerboa.ui.components.common.simpleVerticalScrollbar +import com.jerboa.ui.components.post.PostListing import it.vercruysse.lemmyapi.v0x19.datatypes.BlockPerson import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityFollowerView import it.vercruysse.lemmyapi.v0x19.datatypes.CreateCommentLike +import it.vercruysse.lemmyapi.v0x19.datatypes.CreatePostLike import it.vercruysse.lemmyapi.v0x19.datatypes.DeleteComment +import it.vercruysse.lemmyapi.v0x19.datatypes.DeletePost import it.vercruysse.lemmyapi.v0x19.datatypes.SaveComment +import it.vercruysse.lemmyapi.v0x19.datatypes.SavePost import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.launch @@ -63,7 +71,7 @@ fun SearchActivity( appState: JerboaAppState, selectCommunityMode: Boolean = false, followList: ImmutableList, - blurNSFW: Int, + appSettings: AppSettings, drawerState: DrawerState, accountViewModel: AccountViewModel, siteViewModel: SiteViewModel, @@ -98,8 +106,14 @@ fun SearchActivity( content = { padding -> Column( - Modifier.padding(padding).imePadding(), + Modifier + .padding(padding) + .imePadding(), ) { + if (searchListViewModel.loading || searchListViewModel.searchRes is ApiState.Loading) { + LoadingBar() + } + AnimatedVisibility( visible = showSearchOptions, enter = expandVertically(), @@ -131,10 +145,6 @@ fun SearchActivity( when (val communitiesRes = searchListViewModel.searchRes) { is ApiState.Failure -> ApiErrorText(communitiesRes.msg) - ApiState.Loading -> { - LoadingBar() - } - is ApiState.Success -> { val listState = rememberLazyListState() @@ -196,7 +206,7 @@ fun SearchActivity( appState.toCommunity(id = cs.id) } }, - blurNSFW = blurNSFW, + blurNSFW = appSettings.blurNSFW, ) commentNodeItems( @@ -335,8 +345,123 @@ fun SearchActivity( enableDownVotes = siteViewModel.enableDownvotes(), showAvatar = siteViewModel.showAvatar(), showScores = siteViewModel.showScores(), - blurNSFW = blurNSFW, + blurNSFW = appSettings.blurNSFW, ) + items(communitiesRes.data.posts) { postView -> + PostListing( + postView = postView, + onUpvoteClick = { pv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + siteViewModel, + accountViewModel, + ) { + searchListViewModel.likePost( + CreatePostLike( + post_id = pv.post.id, + score = + newVote( + postView.my_vote, + VoteType.Upvote, + ), + ), + ) + } + }, + onDownvoteClick = { pv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + siteViewModel, + accountViewModel, + ) { + searchListViewModel.likePost( + CreatePostLike( + post_id = pv.post.id, + score = + newVote( + postView.my_vote, + VoteType.Downvote, + ), + ), + ) + } + }, + onReplyClick = { pv -> + appState.toCommentReply( + replyItem = ReplyItem.PostItem(pv), + ) + }, + onPostClick = {}, + onSaveClick = { pv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + siteViewModel, + accountViewModel, + ) { + searchListViewModel.savePost( + SavePost( + post_id = pv.post.id, + save = !pv.saved, + ), + ) + } + }, + onCommunityClick = { community -> + appState.toCommunity(id = community.id) + }, + onEditPostClick = { pv -> + appState.toPostEdit( + postView = pv, + ) + }, + onDeletePostClick = { pv -> + account.doIfReadyElseDisplayInfo( + appState, + ctx, + snackbarHostState, + scope, + siteViewModel, + accountViewModel, + ) { + searchListViewModel.deletePost( + DeletePost( + post_id = pv.post.id, + deleted = !pv.post.deleted, + ), + ) + } + }, + onReportClick = { pv -> + appState.toPostReport(id = pv.post.id) + }, + onPersonClick = appState::toProfile, + showReply = true, // Do nothing + fullBody = true, + account = account, + postViewMode = PostViewMode.List, + enableDownVotes = siteViewModel.enableDownvotes(), + showAvatar = siteViewModel.showAvatar(), + showScores = siteViewModel.showScores(), + appState = appState, + showIfRead = false, + blurNSFW = appSettings.blurNSFW, + showPostLinkPreview = appSettings.showPostLinkPreviews, + postActionbarMode = appSettings.postActionbarMode, + showVotingArrowsInListView = appSettings.showVotingArrowsInListView, + useCustomTabs = appSettings.useCustomTabs, + usePrivateTabs = appSettings.usePrivateTabs, + ) + Divider() + } } } diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt index 22714ede6..67bee4dd3 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchList.kt @@ -3,9 +3,9 @@ package com.jerboa.ui.components.search import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.* +import androidx.compose.material3.Divider import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -18,7 +18,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview import com.jerboa.R import com.jerboa.ui.components.community.CommunityLinkLarger @@ -83,6 +82,7 @@ fun LazyListScope.searchCommunityListings( item.counts.users_active_month }, ) + Divider() } } @@ -122,7 +122,7 @@ fun TopBarSearchField( unfocusedIndicatorColor = Color.Transparent, disabledIndicatorColor = Color.Transparent, ), - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), + // keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), ) } diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchListings.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchListings.kt index b9884b503..90f313163 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchListings.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchListings.kt @@ -2,6 +2,7 @@ package com.jerboa.ui.components.search import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Divider import it.vercruysse.lemmyapi.v0x19.datatypes.PersonView fun LazyListScope.searchPersonListings( @@ -10,5 +11,6 @@ fun LazyListScope.searchPersonListings( ) { items(personViews) { personView -> SearchListPersonItem(personView = personView, onClickPerson = onPersonClick) + Divider() } } diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt index b14331b40..cbf84ace2 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchParametersField.kt @@ -45,7 +45,7 @@ fun SearchParametersField( Column( modifier = Modifier.padding(16.dp, 16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), ) { Box { ClickableOutlinedTextField( From a337da17dfc804351103e89c31f12b57163c9d42 Mon Sep 17 00:00:00 2001 From: "maarten.vercruysse" Date: Tue, 26 Dec 2023 00:44:04 +0100 Subject: [PATCH 4/4] Fix click posts --- .../java/com/jerboa/ui/components/search/SearchActivity.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt index 11d8b9a50..97f150bc1 100644 --- a/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/search/SearchActivity.kt @@ -397,7 +397,9 @@ fun SearchActivity( replyItem = ReplyItem.PostItem(pv), ) }, - onPostClick = {}, + onPostClick = { + appState.toPost(id = it.post.id) + }, onSaveClick = { pv -> account.doIfReadyElseDisplayInfo( appState,