mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2885 All content | Navigation widget (#1628)
This commit is contained in:
parent
dc47b4ded7
commit
823032a7ea
8 changed files with 269 additions and 29 deletions
|
@ -3,6 +3,7 @@ package com.anytypeio.anytype.feature_allcontent.presentation
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary
|
||||
import com.anytypeio.anytype.core_models.DVSortType
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
|
@ -15,6 +16,7 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
|||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.feature_allcontent.models.AllContentMenuMode
|
||||
import com.anytypeio.anytype.feature_allcontent.models.AllContentSort
|
||||
|
@ -31,8 +33,10 @@ import com.anytypeio.anytype.feature_allcontent.models.mapRelationKeyToSort
|
|||
import com.anytypeio.anytype.feature_allcontent.models.toUiContentItems
|
||||
import com.anytypeio.anytype.feature_allcontent.models.toUiContentTypes
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
|
||||
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
|
||||
import com.anytypeio.anytype.presentation.home.navigation
|
||||
import com.anytypeio.anytype.presentation.objects.getCreateObjectParams
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
|
@ -74,8 +78,9 @@ class AllContentViewModel(
|
|||
private val updateAllContentState: UpdateAllContentState,
|
||||
private val restoreAllContentState: RestoreAllContentState,
|
||||
private val searchObjects: SearchObjects,
|
||||
private val localeProvider: LocaleProvider
|
||||
) : ViewModel() {
|
||||
private val localeProvider: LocaleProvider,
|
||||
private val createObject: CreateObject
|
||||
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
|
||||
|
||||
private val searchResultIds = MutableStateFlow<List<Id>>(emptyList())
|
||||
private val sortState = MutableStateFlow<AllContentSort>(DEFAULT_INITIAL_SORT)
|
||||
|
@ -473,11 +478,17 @@ class AllContentViewModel(
|
|||
fun onItemClicked(item: UiContentItem.Item) {
|
||||
Timber.d("onItemClicked: ${item.id}")
|
||||
val layout = item.layout ?: return
|
||||
viewModelScope.launch {
|
||||
when (val navigation = layout.navigation(
|
||||
proceedWithNavigation(
|
||||
navigation = layout.navigation(
|
||||
target = item.id,
|
||||
space = vmParams.spaceId.id
|
||||
)) {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun proceedWithNavigation(navigation: OpenObjectNavigation) {
|
||||
viewModelScope.launch {
|
||||
when (navigation) {
|
||||
is OpenObjectNavigation.OpenDataView -> {
|
||||
commands.emit(
|
||||
Command.NavigateToSetOrCollection(
|
||||
|
@ -503,6 +514,61 @@ class AllContentViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onHomeClicked() {
|
||||
Timber.d("onHomeClicked")
|
||||
viewModelScope.launch {
|
||||
commands.emit(Command.ExitToVault)
|
||||
}
|
||||
}
|
||||
|
||||
fun onGlobalSearchClicked() {
|
||||
Timber.d("onGlobalSearchClicked")
|
||||
viewModelScope.launch {
|
||||
commands.emit(Command.OpenGlobalSearch)
|
||||
}
|
||||
}
|
||||
|
||||
fun onAddDockClicked() {
|
||||
Timber.d("onAddDockClicked")
|
||||
proceedWithCreateDoc()
|
||||
}
|
||||
|
||||
fun onBackClicked() {
|
||||
Timber.d("onBackClicked")
|
||||
viewModelScope.launch {
|
||||
commands.emit(Command.Back)
|
||||
}
|
||||
}
|
||||
|
||||
fun onCreateObjectOfTypeClicked(objType: ObjectWrapper.Type) {
|
||||
proceedWithCreateDoc(objType)
|
||||
}
|
||||
|
||||
private fun proceedWithCreateDoc(
|
||||
objType: ObjectWrapper.Type? = null
|
||||
) {
|
||||
val startTime = System.currentTimeMillis()
|
||||
val params = objType?.uniqueKey.getCreateObjectParams(objType?.defaultTemplateId)
|
||||
viewModelScope.launch {
|
||||
createObject.async(params).fold(
|
||||
onSuccess = { result ->
|
||||
proceedWithNavigation(
|
||||
navigation = result.obj.navigation()
|
||||
)
|
||||
sendAnalyticsObjectCreateEvent(
|
||||
analytics = analytics,
|
||||
route = EventsDictionary.Routes.objCreateLibrary,
|
||||
startTime = startTime,
|
||||
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key),
|
||||
view = EventsDictionary.View.viewHome,
|
||||
spaceParams = provideParams(space = vmParams.spaceId.id)
|
||||
)
|
||||
},
|
||||
onFailure = { e -> Timber.e(e, "Error while creating a new object") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onTypeClicked(item: UiContentItem.Type) {
|
||||
Timber.d("onTypeClicked: ${item.id}")
|
||||
viewModelScope.launch {
|
||||
|
@ -557,6 +623,9 @@ class AllContentViewModel(
|
|||
data class NavigateToBin(val space: Id) : Command()
|
||||
data class SendToast(val message: String) : Command()
|
||||
data class OpenTypeEditing(val item: UiContentItem.Type) : Command()
|
||||
data object OpenGlobalSearch : Command()
|
||||
data object ExitToVault : Command()
|
||||
data object Back : Command()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
|||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.feature_allcontent.presentation.AllContentViewModel.VmParams
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
|
@ -24,7 +25,8 @@ class AllContentViewModelFactory @Inject constructor(
|
|||
private val updateAllContentState: UpdateAllContentState,
|
||||
private val restoreAllContentState: RestoreAllContentState,
|
||||
private val searchObjects: SearchObjects,
|
||||
private val localeProvider: LocaleProvider
|
||||
private val localeProvider: LocaleProvider,
|
||||
private val createObject: CreateObject
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T =
|
||||
|
@ -38,6 +40,7 @@ class AllContentViewModelFactory @Inject constructor(
|
|||
restoreAllContentState = restoreAllContentState,
|
||||
updateAllContentState = updateAllContentState,
|
||||
searchObjects = searchObjects,
|
||||
localeProvider = localeProvider
|
||||
localeProvider = localeProvider,
|
||||
createObject = createObject
|
||||
) as T
|
||||
}
|
|
@ -12,11 +12,14 @@ import androidx.compose.foundation.layout.WindowInsets
|
|||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.ime
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
|
@ -52,6 +55,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.sp
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.foundation.Divider
|
||||
import com.anytypeio.anytype.core_ui.foundation.components.BottomNavigationMenu
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
|
@ -99,7 +103,12 @@ fun AllContentWrapperScreen(
|
|||
onBinClick: () -> Unit,
|
||||
canPaginate: Boolean,
|
||||
onUpdateLimitSearch: () -> Unit,
|
||||
uiContentState: UiContentState
|
||||
uiContentState: UiContentState,
|
||||
onHomeClicked: () -> Unit,
|
||||
onGlobalSearchClicked: () -> Unit,
|
||||
onAddDocClicked: () -> Unit,
|
||||
onCreateObjectLongClicked: () -> Unit,
|
||||
onBackClicked: () -> Unit
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
||||
|
@ -134,7 +143,12 @@ fun AllContentWrapperScreen(
|
|||
uiItemsState = uiItemsState,
|
||||
lazyListState = lazyListState,
|
||||
uiContentState = uiContentState,
|
||||
onTypeClicked = onTypeClicked
|
||||
onTypeClicked = onTypeClicked,
|
||||
onHomeClicked = onHomeClicked,
|
||||
onGlobalSearchClicked = onGlobalSearchClicked,
|
||||
onAddDocClicked = onAddDocClicked,
|
||||
onCreateObjectLongClicked = onCreateObjectLongClicked,
|
||||
onBackClicked = onBackClicked
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -153,17 +167,41 @@ fun AllContentMainScreen(
|
|||
onTypeClicked: (UiContentItem.Type) -> Unit,
|
||||
onBinClick: () -> Unit,
|
||||
lazyListState: LazyListState,
|
||||
uiContentState: UiContentState
|
||||
uiContentState: UiContentState,
|
||||
onHomeClicked: () -> Unit,
|
||||
onGlobalSearchClicked: () -> Unit,
|
||||
onAddDocClicked: () -> Unit,
|
||||
onCreateObjectLongClicked: () -> Unit,
|
||||
onBackClicked: () -> Unit
|
||||
) {
|
||||
val modifier = Modifier
|
||||
.background(color = colorResource(id = R.color.background_primary))
|
||||
|
||||
var isSearchEmpty by remember { mutableStateOf(true) }
|
||||
|
||||
Scaffold(
|
||||
modifier = modifier
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
containerColor = colorResource(id = R.color.background_primary),
|
||||
bottomBar = {
|
||||
Box(
|
||||
modifier = if (BuildConfig.USE_EDGE_TO_EDGE && Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK)
|
||||
Modifier
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
.padding(bottom = 20.dp)
|
||||
.fillMaxWidth()
|
||||
else
|
||||
Modifier
|
||||
.padding(bottom = 20.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
BottomMenu(
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
onHomeClicked = onHomeClicked,
|
||||
onGlobalSearchClicked = onGlobalSearchClicked,
|
||||
onAddDocClicked = onAddDocClicked,
|
||||
onCreateObjectLongClicked = onCreateObjectLongClicked,
|
||||
onBackClicked = onBackClicked
|
||||
)
|
||||
}
|
||||
},
|
||||
topBar = {
|
||||
Column(
|
||||
modifier = if (BuildConfig.USE_EDGE_TO_EDGE && Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK)
|
||||
|
@ -198,11 +236,13 @@ fun AllContentMainScreen(
|
|||
Modifier
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
.background(color = colorResource(id = R.color.background_primary))
|
||||
else
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.background(color = colorResource(id = R.color.background_primary))
|
||||
|
||||
Box(
|
||||
modifier = contentModifier,
|
||||
|
@ -214,18 +254,22 @@ fun AllContentMainScreen(
|
|||
is UiContentState.Error -> {
|
||||
ErrorState(uiContentState.message)
|
||||
}
|
||||
|
||||
is UiContentState.Idle -> {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
UiContentState.InitLoading -> {
|
||||
LoadingState()
|
||||
}
|
||||
|
||||
UiContentState.Paging -> {}
|
||||
UiContentState.Empty -> {
|
||||
EmptyState(isSearchEmpty = isSearchEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
ContentItems(
|
||||
uiItemsState = uiItemsState,
|
||||
|
@ -241,6 +285,27 @@ fun AllContentMainScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BottomMenu(
|
||||
modifier: Modifier = Modifier,
|
||||
onHomeClicked: () -> Unit,
|
||||
onGlobalSearchClicked: () -> Unit,
|
||||
onAddDocClicked: () -> Unit,
|
||||
onCreateObjectLongClicked: () -> Unit,
|
||||
onBackClicked: () -> Unit
|
||||
) {
|
||||
val isImeVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
|
||||
if (isImeVisible) return
|
||||
BottomNavigationMenu(
|
||||
modifier = modifier,
|
||||
backClick = onBackClicked,
|
||||
onProfileClicked = onHomeClicked,
|
||||
searchClick = onGlobalSearchClicked,
|
||||
addDocClick = onAddDocClicked,
|
||||
onCreateObjectLongClicked = onCreateObjectLongClicked
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentItems(
|
||||
uiItemsState: List<UiContentItem>,
|
||||
|
@ -329,7 +394,7 @@ private fun ContentItems(
|
|||
|
||||
LaunchedEffect(key1 = uiContentState) {
|
||||
if (uiContentState is UiContentState.Idle) {
|
||||
if (uiContentState.scrollToTop) {
|
||||
if (uiContentState.scrollToTop) {
|
||||
scope.launch {
|
||||
lazyListState.scrollToItem(0)
|
||||
}
|
||||
|
@ -366,7 +431,13 @@ fun PreviewMainScreen() {
|
|||
AllContentMainScreen(
|
||||
uiItemsState = emptyList(),
|
||||
uiTitleState = UiTitleState.AllContent,
|
||||
uiTabsState = UiTabsState(tabs = listOf(AllContentTab.PAGES, AllContentTab.TYPES, AllContentTab.LISTS), selectedTab = AllContentTab.LISTS),
|
||||
uiTabsState = UiTabsState(
|
||||
tabs = listOf(
|
||||
AllContentTab.PAGES,
|
||||
AllContentTab.TYPES,
|
||||
AllContentTab.LISTS
|
||||
), selectedTab = AllContentTab.LISTS
|
||||
),
|
||||
uiMenuState = UiMenuState.Hidden,
|
||||
onTabClick = {},
|
||||
onQueryChanged = {},
|
||||
|
@ -376,7 +447,12 @@ fun PreviewMainScreen() {
|
|||
onBinClick = {},
|
||||
lazyListState = rememberLazyListState(),
|
||||
uiContentState = UiContentState.Error("Error message"),
|
||||
onTypeClicked = {}
|
||||
onTypeClicked = {},
|
||||
onHomeClicked = {},
|
||||
onGlobalSearchClicked = {},
|
||||
onAddDocClicked = {},
|
||||
onCreateObjectLongClicked = {},
|
||||
onBackClicked = {}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue