From 3d8891f8a09ada56e30d471bd13a76d37bae962b Mon Sep 17 00:00:00 2001 From: Diego Beraldin Date: Thu, 21 Mar 2024 23:39:06 +0100 Subject: [PATCH] feat: explore other instance (#620) --- .../kotlin/DefaultDetailOpenerTest.kt | 4 +- .../detailopener/impl/DefaultDetailOpener.kt | 13 +- .../core/commonui/lemmyui/Options.kt | 1 + .../lemmy/repository/CommunityRepository.kt | 3 +- .../repository/DefaultCommunityRepository.kt | 40 ++-- unit/communitydetail/build.gradle.kts | 15 +- .../communitydetail/CommunityDetailScreen.kt | 26 ++- .../CommunityDetailViewModel.kt | 2 +- .../unit/explore/ExploreScreen.kt | 114 +++++++----- .../unit/explore/ExploreViewModel.kt | 21 ++- .../unit/explore/components/ExploreTopBar.kt | 39 +++- .../unit/explore/di/ExploreModule.kt | 3 +- .../unit/postdetail/PostDetailScreen.kt | 2 +- unit/userdetail/build.gradle.kts | 15 +- .../unit/userdetail/UserDetailScreen.kt | 171 ++++++++---------- 15 files changed, 278 insertions(+), 191 deletions(-) diff --git a/core/commonui/detailopener-impl/src/androidUnitTest/kotlin/DefaultDetailOpenerTest.kt b/core/commonui/detailopener-impl/src/androidUnitTest/kotlin/DefaultDetailOpenerTest.kt index 866436e7c..3b3f384f3 100644 --- a/core/commonui/detailopener-impl/src/androidUnitTest/kotlin/DefaultDetailOpenerTest.kt +++ b/core/commonui/detailopener-impl/src/androidUnitTest/kotlin/DefaultDetailOpenerTest.kt @@ -74,7 +74,7 @@ class DefaultDetailOpenerTest { val community = CommunityModel(name = communityName, id = 1, host = otherInstance) every { identityRepository.authToken } returns MutableStateFlow(token) coEvery { - communityRepository.getAll( + communityRepository.search( query = any(), auth = any(), page = any(), @@ -94,7 +94,7 @@ class DefaultDetailOpenerTest { assertIs(it) }, ) - communityRepository.getAll( + communityRepository.search( query = communityName, auth = token, page = any(), diff --git a/core/commonui/detailopener-impl/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/detailopener/impl/DefaultDetailOpener.kt b/core/commonui/detailopener-impl/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/detailopener/impl/DefaultDetailOpener.kt index 7f6227caf..651449dcc 100644 --- a/core/commonui/detailopener-impl/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/detailopener/impl/DefaultDetailOpener.kt +++ b/core/commonui/detailopener-impl/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/detailopener/impl/DefaultDetailOpener.kt @@ -40,11 +40,12 @@ class DefaultDetailOpener( val (actualCommunity, actualInstance) = withContext(Dispatchers.IO) { val defaultResult = community to otherInstance if (otherInstance.isEmpty()) { - return@withContext defaultResult - } - val found = searchCommunity(name = community.name, host = otherInstance) - if (found != null) { - found to "" + val found = searchCommunity(name = community.name, host = otherInstance) + if (found != null) { + found to "" + } else { + defaultResult + } } else { defaultResult } @@ -165,7 +166,7 @@ class DefaultDetailOpener( val auth = identityRepository.authToken.value tailrec suspend fun searchRec(page: Int = 0): CommunityModel? { - val results = communityRepository.getAll( + val results = communityRepository.search( auth = auth, query = name, resultType = SearchResultType.Communities, diff --git a/core/commonui/lemmyui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/lemmyui/Options.kt b/core/commonui/lemmyui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/lemmyui/Options.kt index 2761b70aa..093ade8b5 100644 --- a/core/commonui/lemmyui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/lemmyui/Options.kt +++ b/core/commonui/lemmyui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/lemmyui/Options.kt @@ -32,4 +32,5 @@ sealed class OptionId(val value: Int) { data object SetCustomSort : OptionId(24) data object Search : OptionId(25) data object Copy : OptionId(26) + data object ExploreInstance : OptionId(27) } diff --git a/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommunityRepository.kt b/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommunityRepository.kt index b01f88c0a..5691622f4 100644 --- a/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommunityRepository.kt +++ b/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommunityRepository.kt @@ -13,12 +13,13 @@ interface CommunityRepository { const val DEFAULT_PAGE_SIZE = 20 } - suspend fun getAll( + suspend fun search( query: String = "", auth: String? = null, page: Int, limit: Int = DEFAULT_PAGE_SIZE, communityId: Int? = null, + instance: String? = null, listingType: ListingType = ListingType.All, sortType: SortType = SortType.Active, resultType: SearchResultType = SearchResultType.All, diff --git a/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/DefaultCommunityRepository.kt b/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/DefaultCommunityRepository.kt index 918b644c6..2ad400ccd 100644 --- a/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/DefaultCommunityRepository.kt +++ b/domain/lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/DefaultCommunityRepository.kt @@ -23,28 +23,44 @@ internal class DefaultCommunityRepository( private val customServices: ServiceProvider, ) : CommunityRepository { - override suspend fun getAll( + override suspend fun search( query: String, auth: String?, page: Int, limit: Int, communityId: Int?, + instance: String?, listingType: ListingType, sortType: SortType, resultType: SearchResultType, ): List = withContext(Dispatchers.IO) { runCatching { - val searchResponse = services.search.search( - authHeader = auth.toAuthHeader(), - q = query, - auth = auth, - page = page, - limit = limit, - communityId = communityId, - type = resultType.toDto(), - listingType = listingType.toDto(), - sort = sortType.toDto(), - ).body() + val searchResponse = if (instance.isNullOrEmpty()) { + services.search.search( + authHeader = auth.toAuthHeader(), + q = query, + auth = auth, + page = page, + limit = limit, + communityId = communityId, + type = resultType.toDto(), + listingType = listingType.toDto(), + sort = sortType.toDto(), + ).body() + } else { + customServices.changeInstance(instance) + customServices.search.search( + authHeader = auth.toAuthHeader(), + q = query, + auth = auth, + page = page, + limit = limit, + communityId = communityId, + type = resultType.toDto(), + listingType = listingType.toDto(), + sort = sortType.toDto(), + ).body() + } buildList { val posts = searchResponse?.posts?.map { it.toModel() }.orEmpty() this += posts.map { SearchResult.Post(it) } diff --git a/unit/communitydetail/build.gradle.kts b/unit/communitydetail/build.gradle.kts index 09f2b9a51..dd704e616 100644 --- a/unit/communitydetail/build.gradle.kts +++ b/unit/communitydetail/build.gradle.kts @@ -55,18 +55,19 @@ kotlin { implementation(projects.domain.lemmy.data) implementation(projects.domain.lemmy.repository) - implementation(projects.unit.zoomableimage) - implementation(projects.unit.web) - implementation(projects.unit.createreport) - implementation(projects.unit.createcomment) - implementation(projects.unit.createpost) - implementation(projects.unit.remove) implementation(projects.unit.ban) implementation(projects.unit.communityinfo) + implementation(projects.unit.createcomment) + implementation(projects.unit.createpost) + implementation(projects.unit.createreport) + implementation(projects.unit.explore) implementation(projects.unit.instanceinfo) - implementation(projects.unit.reportlist) implementation(projects.unit.modlog) implementation(projects.unit.rawcontent) + implementation(projects.unit.remove) + implementation(projects.unit.reportlist) + implementation(projects.unit.web) + implementation(projects.unit.zoomableimage) } } val commonTest by getting { diff --git a/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailScreen.kt b/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailScreen.kt index 03b88c2ca..920ccbe6d 100644 --- a/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailScreen.kt +++ b/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailScreen.kt @@ -4,7 +4,6 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.gestures.animateScrollBy @@ -127,6 +126,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt import com.github.diegoberaldin.raccoonforlemmy.unit.ban.BanUserScreen import com.github.diegoberaldin.raccoonforlemmy.unit.communityinfo.CommunityInfoScreen import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen +import com.github.diegoberaldin.raccoonforlemmy.unit.explore.ExploreScreen import com.github.diegoberaldin.raccoonforlemmy.unit.instanceinfo.InstanceInfoScreen import com.github.diegoberaldin.raccoonforlemmy.unit.modlog.ModlogScreen import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog @@ -147,7 +147,7 @@ class CommunityDetailScreen( override val key: ScreenKey get() = super.key + communityId.toString() - @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class, ExperimentalFoundationApi::class) + @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) @Composable override fun Content() { val model = getScreenModel( @@ -338,6 +338,17 @@ class CommunityDetailScreen( OptionId.InfoInstance, LocalXmlStrings.current.communityDetailInstanceInfo ) + this += Option( + OptionId.ExploreInstance, + buildString { + append(LocalXmlStrings.current.navigationSearch) + append(" ") + append(uiState.community.host) + append(" (") + append(LocalXmlStrings.current.beta) + append(")") + }, + ) this += Option( OptionId.Share, LocalXmlStrings.current.postActionShare ) @@ -379,7 +390,7 @@ class CommunityDetailScreen( Image( modifier = Modifier.onGloballyPositioned { optionsOffset = it.positionInParent() - }.padding(start = Spacing.s).onClick( + }.onClick( onClick = rememberCallback { optionsExpanded = true }, @@ -481,6 +492,11 @@ class CommunityDetailScreen( model.reduce(CommunityDetailMviModel.Intent.ChangeSearching(!uiState.searching)) } + OptionId.ExploreInstance -> { + val screen = ExploreScreen(otherInstance = uiState.community.host) + navigationCoordinator.pushScreen(screen) + } + else -> Unit } }, @@ -754,12 +770,12 @@ class CommunityDetailScreen( onGestureBegin = rememberCallback(model) { model.reduce(CommunityDetailMviModel.Intent.HapticIndication) }, - swipeToStartActions = if (uiState.isLogged) { + swipeToStartActions = if (uiState.isLogged && !isOnOtherInstance) { uiState.actionsOnSwipeToStartPosts.toSwipeActions() } else { emptyList() }, - swipeToEndActions = if (uiState.isLogged) { + swipeToEndActions = if (uiState.isLogged && !isOnOtherInstance) { uiState.actionsOnSwipeToEndPosts.toSwipeActions() } else { emptyList() diff --git a/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailViewModel.kt b/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailViewModel.kt index d0164d4b4..fea743481 100644 --- a/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailViewModel.kt +++ b/unit/communitydetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/communitydetail/CommunityDetailViewModel.kt @@ -352,7 +352,7 @@ class CommunityDetailViewModel( val includeNsfw = settingsRepository.currentSettings.value.includeNsfw val (itemList, nextPage) = if (currentState.searching) { - communityRepository.getAll( + communityRepository.search( auth = auth, communityId = community.id, page = currentPage, diff --git a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreScreen.kt b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreScreen.kt index 13b71d866..7b26fbbab 100644 --- a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreScreen.kt +++ b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreScreen.kt @@ -91,6 +91,7 @@ import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImage import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import org.koin.core.parameter.parametersOf class ExploreScreen( private val otherInstance: String = "", @@ -99,7 +100,7 @@ class ExploreScreen( @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) @Composable override fun Content() { - val model = getScreenModel() + val model = getScreenModel(parameters = { parametersOf(otherInstance) }) val uiState by model.uiState.collectAsState() val navigationCoordinator = remember { getNavigationCoordinator() } val topAppBarState = rememberTopAppBarState() @@ -133,6 +134,13 @@ class ExploreScreen( val otherInstanceName = remember { otherInstance } val snackbarHostState = remember { SnackbarHostState() } val errorMessage = LocalXmlStrings.current.messageGenericError + val notificationEventKey = buildString { + append("explore") + if (isOnOtherInstance) { + append("-") + append(otherInstanceName) + } + } LaunchedEffect(navigationCoordinator) { navigationCoordinator.onDoubleTabSelection.onEach { section -> @@ -172,11 +180,12 @@ class ExploreScreen( listingType = uiState.listingType, sortType = uiState.sortType, resultType = uiState.resultType, + otherInstance = otherInstanceName, onSelectListingType = rememberCallback { focusManager.clearFocus() val sheet = ListingTypeBottomSheet( isLogged = uiState.isLogged, - screenKey = "explore", + screenKey = notificationEventKey, ) navigationCoordinator.showBottomSheet(sheet) }, @@ -185,20 +194,12 @@ class ExploreScreen( val sheet = SortBottomSheet( values = uiState.availableSortTypes.map { it.toInt() }, expandTop = true, - screenKey = "explore", + screenKey = notificationEventKey, ) navigationCoordinator.showBottomSheet(sheet) }, onSelectResultTypeType = rememberCallback { - val sheet = ResultTypeBottomSheet( - screenKey = buildString { - append("explore") - if (isOnOtherInstance) { - append("-") - append(otherInstanceName) - } - } - ) + val sheet = ResultTypeBottomSheet(screenKey = notificationEventKey) navigationCoordinator.showBottomSheet(sheet) }, onHamburgerTapped = rememberCallback { @@ -206,6 +207,9 @@ class ExploreScreen( drawerCoordinator.toggleDrawer() } }, + onBack = rememberCallback { + navigationCoordinator.popScreen() + } ) }, snackbarHost = { @@ -296,7 +300,10 @@ class ExploreScreen( CommunityItem( modifier = Modifier.fillMaxWidth().onClick( onClick = rememberCallback { - detailOpener.openCommunityDetail(result.model) + detailOpener.openCommunityDetail( + community = result.model, + otherInstance = otherInstanceName, + ) }, ), community = result.model, @@ -393,7 +400,7 @@ class ExploreScreen( SwipeActionCard( modifier = Modifier.fillMaxWidth(), - enabled = uiState.swipeActionsEnabled, + enabled = uiState.swipeActionsEnabled && !isOnOtherInstance, onGestureBegin = rememberCallback(model) { model.reduce(ExploreMviModel.Intent.HapticIndication) }, @@ -420,9 +427,12 @@ class ExploreScreen( blurNsfw = uiState.blurNsfw, actionButtonsActive = uiState.isLogged, onClick = rememberCallback { - detailOpener.openPostDetail(result.model) + detailOpener.openPostDetail( + post = result.model, + otherInstance = otherInstanceName, + ) }, - onDoubleClick = if (!uiState.doubleTapActionEnabled) { + onDoubleClick = if (!uiState.doubleTapActionEnabled || isOnOtherInstance) { null } else { rememberCallback(model) { @@ -438,37 +448,38 @@ class ExploreScreen( }, onOpenCommunity = rememberCallbackArgs { community, instance -> detailOpener.openCommunityDetail( - community, - instance, + community = community, + otherInstance = instance.takeIf { + it.isNotEmpty() + } ?: otherInstanceName, ) }, onOpenCreator = rememberCallbackArgs { user, instance -> - detailOpener.openUserDetail(user, instance) + detailOpener.openUserDetail( + user = user, + otherInstance = instance.takeIf { + it.isNotEmpty() + } ?: otherInstanceName, + ) }, onUpVote = rememberCallback(model) { if (uiState.isLogged) { model.reduce( - ExploreMviModel.Intent.UpVotePost( - id = result.model.id, - ), + ExploreMviModel.Intent.UpVotePost(result.model.id), ) } }, onDownVote = rememberCallback(model) { if (uiState.isLogged) { model.reduce( - ExploreMviModel.Intent.DownVotePost( - id = result.model.id, - ), + ExploreMviModel.Intent.DownVotePost(result.model.id), ) } }, onSave = rememberCallback(model) { if (uiState.isLogged) { model.reduce( - ExploreMviModel.Intent.SavePost( - id = result.model.id, - ), + ExploreMviModel.Intent.SavePost(result.model.id), ) } }, @@ -481,7 +492,12 @@ class ExploreScreen( ) }, onOpenPost = rememberCallbackArgs { post, instance -> - detailOpener.openPostDetail(post, instance) + detailOpener.openPostDetail( + post = post, + otherInstance = instance.takeIf { + it.isNotEmpty() + } ?: otherInstanceName, + ) }, onOpenWeb = rememberCallbackArgs { url -> @@ -516,9 +532,7 @@ class ExploreScreen( ?: defaultUpvoteColor, onTriggered = rememberCallback { model.reduce( - ExploreMviModel.Intent.UpVoteComment( - result.model.id - ) + ExploreMviModel.Intent.UpVoteComment(result.model.id) ) }, ) @@ -535,9 +549,7 @@ class ExploreScreen( ?: defaultDownVoteColor, onTriggered = rememberCallback { model.reduce( - ExploreMviModel.Intent.DownVoteComment( - result.model.id - ), + ExploreMviModel.Intent.DownVoteComment(result.model.id), ) }, ) @@ -556,6 +568,7 @@ class ExploreScreen( detailOpener.openPostDetail( post = PostModel(id = result.model.postId), highlightCommentId = result.model.id, + otherInstance = otherInstanceName, ) }, ) @@ -572,9 +585,7 @@ class ExploreScreen( ?: defaultSaveColor, onTriggered = rememberCallback { model.reduce( - ExploreMviModel.Intent.SaveComment( - id = result.model.id, - ), + ExploreMviModel.Intent.SaveComment(result.model.id), ) }, ) @@ -615,6 +626,7 @@ class ExploreScreen( detailOpener.openPostDetail( post = PostModel(id = result.model.postId), highlightCommentId = result.model.id, + otherInstance = otherInstanceName, ) }, onDoubleClick = if (!uiState.doubleTapActionEnabled) { @@ -660,23 +672,30 @@ class ExploreScreen( }, onOpenCommunity = rememberCallbackArgs { community, instance -> detailOpener.openCommunityDetail( - community, - instance, + community = community, + otherInstance = instance.takeIf { + it.isNotEmpty() + } ?: otherInstanceName, ) }, onOpenCreator = rememberCallbackArgs { user, instance -> - detailOpener.openUserDetail(user, instance) + detailOpener.openUserDetail( + user = user, + otherInstance = instance.takeIf { + it.isNotEmpty() + } ?: otherInstanceName, + ) }, onOpenPost = rememberCallbackArgs { post, instance -> detailOpener.openPostDetail( post = post, - otherInstance = instance, + otherInstance = instance.takeIf { + it.isNotEmpty() + } ?: otherInstanceName, ) }, onOpenWeb = rememberCallbackArgs { url -> - navigationCoordinator.pushScreen( - WebViewScreen(url) - ) + navigationCoordinator.pushScreen(WebViewScreen(url)) }, ) }, @@ -691,7 +710,10 @@ class ExploreScreen( UserItem( modifier = Modifier.fillMaxWidth().onClick( onClick = rememberCallback { - detailOpener.openUserDetail(result.model, "") + detailOpener.openUserDetail( + user = result.model, + otherInstance = otherInstanceName, + ) }, ), user = result.model, diff --git a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreViewModel.kt b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreViewModel.kt index 279444efb..5132245ea 100644 --- a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreViewModel.kt +++ b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/ExploreViewModel.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.launch @OptIn(FlowPreview::class) class ExploreViewModel( + private val otherInstance: String, private val apiConfigRepository: ApiConfigurationRepository, private val identityRepository: IdentityRepository, private val communityRepository: CommunityRepository, @@ -52,6 +53,15 @@ class ExploreViewModel( private var currentPage: Int = 1 private var searchEventChannel = Channel() + private val isOnOtherInstance: Boolean get() = otherInstance.isNotEmpty() + private val notificationEventKey: String + get() = buildString { + append("explore") + if (isOnOtherInstance) { + append("-") + append(otherInstance) + } + } init { updateState { @@ -99,13 +109,13 @@ class ExploreViewModel( }.launchIn(this) notificationCenter.subscribe(NotificationCenterEvent.ChangeFeedType::class) .onEach { evt -> - if (evt.screenKey == "explore") { + if (evt.screenKey == notificationEventKey) { changeListingType(evt.value) } }.launchIn(this) notificationCenter.subscribe(NotificationCenterEvent.ChangeSortType::class) .onEach { evt -> - if (evt.screenKey == "explore") { + if (evt.screenKey == notificationEventKey) { changeSortType(evt.value) } }.launchIn(this) @@ -113,7 +123,7 @@ class ExploreViewModel( onFirstLoad() }.launchIn(this) notificationCenter.subscribe(NotificationCenterEvent.ChangeSearchResultType::class).onEach { evt -> - if (evt.screenKey == "explore") { + if (evt.screenKey == notificationEventKey) { changeResultType(evt.value) } }.launchIn(this) @@ -129,7 +139,7 @@ class ExploreViewModel( private fun onFirstLoad() { val settings = settingsRepository.currentSettings.value - val listingType = settings.defaultExploreType.toListingType() + val listingType = if (isOnOtherInstance) ListingType.Local else settings.defaultExploreType.toListingType() val sortType = settings.defaultPostSortType.toSortType() updateState { it.copy( @@ -297,13 +307,14 @@ class ExploreViewModel( val sortType = currentState.sortType val resultType = currentState.resultType val settings = settingsRepository.currentSettings.value - val itemList = communityRepository.getAll( + val itemList = communityRepository.search( query = searchText, auth = auth, resultType = resultType, page = currentPage, listingType = listingType, sortType = sortType, + instance = otherInstance, ) val additionalResolvedCommunity = if (resultType == SearchResultType.All || resultType == SearchResultType.Communities && currentPage == 1) { diff --git a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/components/ExploreTopBar.kt b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/components/ExploreTopBar.kt index 50c644869..8297c7f3d 100644 --- a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/components/ExploreTopBar.kt +++ b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/components/ExploreTopBar.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Menu import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -34,15 +35,30 @@ internal fun ExploreTopBar( listingType: ListingType, sortType: SortType, resultType: SearchResultType, + otherInstance: String = "", onSelectListingType: (() -> Unit)? = null, onSelectSortType: (() -> Unit)? = null, onSelectResultTypeType: (() -> Unit)? = null, onHamburgerTapped: (() -> Unit)? = null, + onBack: (() -> Unit)? = null, ) { TopAppBar( scrollBehavior = scrollBehavior, navigationIcon = { when { + otherInstance.isNotEmpty() -> { + Image( + modifier = Modifier.onClick( + onClick = rememberCallback { + onBack?.invoke() + }, + ), + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = null, + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground), + ) + } + onHamburgerTapped != null -> { Image( modifier = Modifier.onClick( @@ -77,18 +93,29 @@ internal fun ExploreTopBar( .padding(horizontal = Spacing.s) .onClick( onClick = rememberCallback { - onSelectListingType?.invoke() + if (otherInstance.isEmpty()) { + onSelectListingType?.invoke() + } }, ), ) { Text( - text = LocalXmlStrings.current.navigationSearch, + text = buildString { + append(LocalXmlStrings.current.navigationSearch) + if (otherInstance.isNotEmpty()) { + append(" (") + append(otherInstance) + append(")") + } + }, style = MaterialTheme.typography.titleMedium, ) - Text( - text = listingType.toReadableName(), - style = MaterialTheme.typography.titleSmall, - ) + if (otherInstance.isEmpty()) { + Text( + text = listingType.toReadableName(), + style = MaterialTheme.typography.titleSmall, + ) + } } }, actions = { diff --git a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/di/ExploreModule.kt b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/di/ExploreModule.kt index f5070a8f4..bab8a9847 100644 --- a/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/di/ExploreModule.kt +++ b/unit/explore/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/explore/di/ExploreModule.kt @@ -5,8 +5,9 @@ import com.github.diegoberaldin.raccoonforlemmy.unit.explore.ExploreViewModel import org.koin.dsl.module val exploreModule = module { - factory { + factory { params -> ExploreViewModel( + otherInstance = params[0], apiConfigRepository = get(), identityRepository = get(), communityRepository = get(), diff --git a/unit/postdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/postdetail/PostDetailScreen.kt b/unit/postdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/postdetail/PostDetailScreen.kt index 834c4e639..082cdc2a2 100644 --- a/unit/postdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/postdetail/PostDetailScreen.kt +++ b/unit/postdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/postdetail/PostDetailScreen.kt @@ -293,7 +293,7 @@ class PostDetailScreen( Image( modifier = Modifier.onGloballyPositioned { optionsOffset = it.positionInParent() - }.padding(start = Spacing.s).onClick( + }.onClick( onClick = rememberCallback { optionsExpanded = true }, diff --git a/unit/userdetail/build.gradle.kts b/unit/userdetail/build.gradle.kts index 1eb9a638b..1b85a3f45 100644 --- a/unit/userdetail/build.gradle.kts +++ b/unit/userdetail/build.gradle.kts @@ -55,16 +55,17 @@ kotlin { implementation(projects.domain.lemmy.data) implementation(projects.domain.lemmy.repository) - implementation(projects.unit.zoomableimage) - implementation(projects.unit.web) - implementation(projects.unit.createreport) - implementation(projects.unit.createcomment) - implementation(projects.unit.createpost) - implementation(projects.unit.remove) implementation(projects.unit.ban) implementation(projects.unit.chat) - implementation(projects.unit.userinfo) + implementation(projects.unit.createcomment) + implementation(projects.unit.createpost) + implementation(projects.unit.createreport) + implementation(projects.unit.explore) implementation(projects.unit.rawcontent) + implementation(projects.unit.remove) + implementation(projects.unit.userinfo) + implementation(projects.unit.web) + implementation(projects.unit.zoomableimage) } } val commonTest by getting { diff --git a/unit/userdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/userdetail/UserDetailScreen.kt b/unit/userdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/userdetail/UserDetailScreen.kt index 136f32d63..30cab10b0 100644 --- a/unit/userdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/userdetail/UserDetailScreen.kt +++ b/unit/userdetail/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/unit/userdetail/UserDetailScreen.kt @@ -113,6 +113,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt import com.github.diegoberaldin.raccoonforlemmy.unit.chat.InboxChatScreen import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen +import com.github.diegoberaldin.raccoonforlemmy.unit.explore.ExploreScreen import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog import com.github.diegoberaldin.raccoonforlemmy.unit.userinfo.UserInfoScreen import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen @@ -246,10 +247,23 @@ class UserDetailScreen( Box { val options = buildList { this += Option( - OptionId.Info, LocalXmlStrings.current.userDetailInfo + OptionId.Info, + LocalXmlStrings.current.userDetailInfo ) this += Option( - OptionId.Share, LocalXmlStrings.current.postActionShare + OptionId.ExploreInstance, + buildString { + append(LocalXmlStrings.current.navigationSearch) + append(" ") + append(uiState.user.host) + append(" (") + append(LocalXmlStrings.current.beta) + append(")") + }, + ) + this += Option( + OptionId.Share, + LocalXmlStrings.current.postActionShare ) if (uiState.isLogged) { this += Option( @@ -267,7 +281,7 @@ class UserDetailScreen( Image( modifier = Modifier.onGloballyPositioned { optionsOffset = it.positionInParent() - }.padding(start = Spacing.s).onClick( + }.onClick( onClick = rememberCallback { optionsExpanded = true }, @@ -294,18 +308,16 @@ class UserDetailScreen( onClick = rememberCallback { optionsExpanded = false when (option.id) { - OptionId.BlockInstance -> model.reduce( - UserDetailMviModel.Intent.BlockInstance - ) + OptionId.BlockInstance -> { + model.reduce(UserDetailMviModel.Intent.BlockInstance) + } - OptionId.Block -> model.reduce( - UserDetailMviModel.Intent.Block - ) + OptionId.Block -> { + model.reduce(UserDetailMviModel.Intent.Block) + } OptionId.Info -> { - navigationCoordinator.showBottomSheet( - UserInfoScreen(uiState.user.id), - ) + navigationCoordinator.showBottomSheet(UserInfoScreen(uiState.user.id)) } OptionId.Share -> { @@ -317,19 +329,19 @@ class UserDetailScreen( } if (urls.size == 1) { model.reduce( - UserDetailMviModel.Intent.Share( - urls.first() - ) + UserDetailMviModel.Intent.Share(urls.first()) ) } else { - val screen = - ShareBottomSheet(urls = urls) - navigationCoordinator.showBottomSheet( - screen - ) + val screen = ShareBottomSheet(urls = urls) + navigationCoordinator.showBottomSheet(screen) } } + OptionId.ExploreInstance -> { + val screen = ExploreScreen(otherInstance = uiState.user.host) + navigationCoordinator.pushScreen(screen) + } + else -> Unit } }, @@ -495,9 +507,7 @@ class UserDetailScreen( ?: defaultUpvoteColor, onTriggered = rememberCallback { model.reduce( - UserDetailMviModel.Intent.UpVotePost( - post.id, - ), + UserDetailMviModel.Intent.UpVotePost(post.id), ) }, ) @@ -514,9 +524,7 @@ class UserDetailScreen( ?: defaultDownVoteColor, onTriggered = rememberCallback { model.reduce( - UserDetailMviModel.Intent.DownVotePost( - post.id, - ) + UserDetailMviModel.Intent.DownVotePost(post.id) ) }, ) @@ -548,9 +556,7 @@ class UserDetailScreen( ?: defaultSaveColor, onTriggered = rememberCallback { model.reduce( - UserDetailMviModel.Intent.SavePost( - id = post.id, - ), + UserDetailMviModel.Intent.SavePost(id = post.id), ) }, ) @@ -609,9 +615,7 @@ class UserDetailScreen( } else { rememberCallback(model) { model.reduce( - UserDetailMviModel.Intent.UpVotePost( - id = post.id, - ), + UserDetailMviModel.Intent.UpVotePost(id = post.id), ) } }, @@ -620,9 +624,7 @@ class UserDetailScreen( } else { rememberCallback(model) { model.reduce( - UserDetailMviModel.Intent.DownVotePost( - id = post.id, - ), + UserDetailMviModel.Intent.DownVotePost(post.id), ) } }, @@ -631,28 +633,30 @@ class UserDetailScreen( } else { rememberCallback(model) { model.reduce( - UserDetailMviModel.Intent.SavePost( - id = post.id, - ), + UserDetailMviModel.Intent.SavePost(post.id), ) } }, onOpenCommunity = rememberCallbackArgs { community, instance -> detailOpener.openCommunityDetail( - community, - instance, + community = community, + otherInstance = instance, ) }, onOpenCreator = rememberCallbackArgs { user, instance -> - detailOpener.openUserDetail(user, instance) + detailOpener.openUserDetail( + user = user, + otherInstance = instance + ) }, onOpenPost = rememberCallbackArgs { p, instance -> - detailOpener.openPostDetail(p, instance) + detailOpener.openPostDetail( + post = p, + otherInstance = instance + ) }, onOpenWeb = rememberCallbackArgs { url -> - navigationCoordinator.pushScreen( - WebViewScreen(url) - ) + navigationCoordinator.pushScreen(WebViewScreen(url)) }, onReply = if (!uiState.isLogged || isOnOtherInstance) { null @@ -697,9 +701,7 @@ class UserDetailScreen( when (optionId) { OptionId.Report -> { navigationCoordinator.pushScreen( - CreateReportScreen( - postId = post.id - ) + CreateReportScreen(post.id) ) } @@ -721,16 +723,11 @@ class UserDetailScreen( ).distinct() if (urls.size == 1) { model.reduce( - UserDetailMviModel.Intent.Share( - urls.first() - ) + UserDetailMviModel.Intent.Share(urls.first()) ) } else { - val screen = - ShareBottomSheet(urls = urls) - navigationCoordinator.showBottomSheet( - screen - ) + val screen = ShareBottomSheet(urls = urls) + navigationCoordinator.showBottomSheet(screen) } } @@ -803,9 +800,7 @@ class UserDetailScreen( ?: defaultUpvoteColor, onTriggered = rememberCallback { model.reduce( - UserDetailMviModel.Intent.UpVoteComment( - comment.id - ) + UserDetailMviModel.Intent.UpVoteComment(comment.id) ) }, ) @@ -822,9 +817,7 @@ class UserDetailScreen( ?: defaultDownVoteColor, onTriggered = rememberCallback { model.reduce( - UserDetailMviModel.Intent.DownVoteComment( - comment.id - ), + UserDetailMviModel.Intent.DownVoteComment(comment.id), ) }, ) @@ -859,9 +852,7 @@ class UserDetailScreen( ?: defaultSaveColor, onTriggered = rememberCallback { model.reduce( - UserDetailMviModel.Intent.SaveComment( - id = comment.id, - ), + UserDetailMviModel.Intent.SaveComment(comment.id), ) }, ) @@ -930,9 +921,7 @@ class UserDetailScreen( } else { rememberCallback(model) { model.reduce( - UserDetailMviModel.Intent.SaveComment( - id = comment.id, - ), + UserDetailMviModel.Intent.SaveComment(comment.id), ) } }, @@ -941,9 +930,7 @@ class UserDetailScreen( } else { rememberCallback(model) { model.reduce( - UserDetailMviModel.Intent.UpVoteComment( - id = comment.id, - ), + UserDetailMviModel.Intent.UpVoteComment(comment.id), ) } }, @@ -952,9 +939,7 @@ class UserDetailScreen( } else { rememberCallback(model) { model.reduce( - UserDetailMviModel.Intent.DownVoteComment( - id = comment.id, - ), + UserDetailMviModel.Intent.DownVoteComment(comment.id), ) } }, @@ -969,30 +954,35 @@ class UserDetailScreen( } }, onOpenCommunity = rememberCallbackArgs { community, instance -> - detailOpener.openCommunityDetail(community, instance) + detailOpener.openCommunityDetail( + community = community, + otherInstance = instance + ) }, onOpenCreator = rememberCallbackArgs { user, instance -> - detailOpener.openUserDetail(user, instance) + detailOpener.openUserDetail( + user = user, + otherInstance = instance + ) }, onOpenPost = rememberCallbackArgs { post, instance -> - detailOpener.openPostDetail(post, instance) + detailOpener.openPostDetail( + post = post, + otherInstance = instance + ) }, onOpenWeb = rememberCallbackArgs { url -> navigationCoordinator.pushScreen(WebViewScreen(url)) }, options = buildList { - add( - Option( - OptionId.SeeRaw, - LocalXmlStrings.current.postActionSeeRaw - ) + this += Option( + OptionId.SeeRaw, + LocalXmlStrings.current.postActionSeeRaw, ) if (uiState.isLogged && !isOnOtherInstance) { - add( - Option( - OptionId.Report, - LocalXmlStrings.current.postActionReport - ) + this += Option( + OptionId.Report, + LocalXmlStrings.current.postActionReport, ) } }, @@ -1000,9 +990,7 @@ class UserDetailScreen( when (optionId) { OptionId.Report -> { navigationCoordinator.pushScreen( - CreateReportScreen( - commentId = comment.id - ), + CreateReportScreen(comment.id), ) } @@ -1146,7 +1134,8 @@ class UserDetailScreen( }, ) } - }) + }, + ) } } }