1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-2924 All Content | Bin, empty state + viewer permissions (#1679)

This commit is contained in:
Konstantin Ivanov 2024-10-15 16:41:06 +03:00 committed by Evgenii Kozlov
parent 18ba56bdf4
commit 14af7b40c1
20 changed files with 229 additions and 96 deletions

View file

@ -114,7 +114,9 @@ import com.anytypeio.anytype.presentation.relations.value.`object`.ObjectValueVi
import com.anytypeio.anytype.presentation.relations.value.tagstatus.TagOrStatusValueViewModel
import com.anytypeio.anytype.presentation.search.GlobalSearchViewModel
import com.anytypeio.anytype.presentation.sets.ObjectSetViewModel
import com.anytypeio.anytype.presentation.settings.SpacesStorageViewModel
import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel
import com.anytypeio.anytype.presentation.widgets.collection.CollectionViewModel
import com.anytypeio.anytype.ui.relations.RelationEditParameters
import com.anytypeio.anytype.ui.types.edit.TypeEditParameters
import com.anytypeio.anytype.ui.widgets.collection.DaggerCollectionComponent
@ -155,10 +157,13 @@ class ComponentManager(
.create(findComponentDependencies())
}
val collectionComponent = Component {
val collectionComponent = ComponentWithParams { vmParams: CollectionViewModel.VmParams ->
DaggerCollectionComponent
.factory()
.create(findComponentDependencies())
.create(
dependencies = findComponentDependencies(),
vmParams = vmParams
)
}
val selectWidgetSourceSubcomponent = Component {
@ -720,10 +725,13 @@ class ComponentManager(
.build()
}
val spacesStorageComponent = Component {
DaggerSpacesStorageComponent.builder()
.withDependencies(findComponentDependencies())
.build()
val spacesStorageComponent = ComponentWithParams { vmParams: SpacesStorageViewModel.VmParams ->
DaggerSpacesStorageComponent
.factory()
.create(
vmParams = vmParams,
dependency = findComponentDependencies()
)
}
val appearanceComponent = Component {
@ -843,12 +851,13 @@ class ComponentManager(
.create(findComponentDependencies())
}
val spaceSettingsComponent = ComponentWithParams { space: SpaceId ->
val spaceSettingsComponent = ComponentWithParams { vmParams: SpaceSettingsViewModel.VmParams ->
DaggerSpaceSettingsComponent
.builder()
.withParams(SpaceSettingsViewModel.Params(space))
.withDependencies(findComponentDependencies())
.build()
.factory()
.create(
vmParams = vmParams,
dependencies = findComponentDependencies()
)
}
val selectObjectTypeComponent = ComponentWithParams { params: SelectObjectTypeViewModel.Params ->

View file

@ -19,9 +19,11 @@ import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.membership.provider.MembershipProvider
import com.anytypeio.anytype.presentation.settings.SpacesStorageViewModel
import com.anytypeio.anytype.presentation.settings.SpacesStorageViewModelFactory
import com.anytypeio.anytype.ui.settings.SpacesStorageFragment
import dagger.Binds
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import dagger.Provides
@ -36,11 +38,12 @@ import dagger.Provides
)
interface SpacesStorageComponent {
@Component.Builder
interface Builder {
fun withDependencies(dependency: SpacesStorageDependencies): Builder
fun build(): SpacesStorageComponent
@Component.Factory
interface Factory {
fun create(
@BindsInstance vmParams: SpacesStorageViewModel.VmParams,
dependency: SpacesStorageDependencies
): SpacesStorageComponent
}
fun inject(fragment: SpacesStorageFragment)

View file

@ -41,12 +41,12 @@ import dagger.Provides
)
@PerScreen
interface SpaceSettingsComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun withParams(params: SpaceSettingsViewModel.Params): Builder
fun withDependencies(dependencies: SpaceSettingsDependencies): Builder
fun build(): SpaceSettingsComponent
@Component.Factory
interface Factory {
fun create(
@BindsInstance vmParams: SpaceSettingsViewModel.VmParams,
dependencies: SpaceSettingsDependencies
) : SpaceSettingsComponent
}
fun inject(fragment: SpaceSettingsFragment)

View file

@ -232,9 +232,14 @@ class Navigator : AppNavigation {
)
}
override fun openRemoteFilesManageScreen(subscription: Id) {
navController?.navigate(R.id.remoteStorageFragment,
bundleOf(RemoteFilesManageFragment.SUBSCRIPTION_KEY to subscription))
override fun openRemoteFilesManageScreen(subscription: Id, space: Id) {
navController?.navigate(
resId = R.id.remoteStorageFragment,
args = RemoteFilesManageFragment.args(
subscription = subscription,
space = space
)
)
}
override fun openTemplatesModal(typeId: Id) {

View file

@ -51,9 +51,6 @@ class NavigationRouter(
)
is AppNavigation.Command.OpenLibrary -> navigation.openLibrary(command.space)
is AppNavigation.Command.MigrationErrorScreen -> navigation.migrationErrorScreen()
is AppNavigation.Command.OpenRemoteFilesManageScreen -> navigation.openRemoteFilesManageScreen(
command.subscription
)
else -> Timber.d("Nav command ignored: $command")
}
} catch (e: Exception) {

View file

@ -8,9 +8,12 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.argString
import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
import com.anytypeio.anytype.core_utils.ext.toast
@ -32,6 +35,8 @@ class RemoteFilesManageFragment : BaseBottomSheetComposeFragment() {
private val navigation get() = navigation()
private val space get() = arg<Id>(SPACE_ID_KEY)
private val subscription: Subscription by lazy {
SubscriptionMapper().map(argString(SUBSCRIPTION_KEY))
}
@ -127,7 +132,10 @@ class RemoteFilesManageFragment : BaseBottomSheetComposeFragment() {
}
override fun injectDependencies() {
componentManager().collectionComponent.get().inject(this)
val vmParams = CollectionViewModel.VmParams(
spaceId = SpaceId(space)
)
componentManager().collectionComponent.get(vmParams).inject(this)
}
override fun releaseDependencies() {
@ -136,6 +144,11 @@ class RemoteFilesManageFragment : BaseBottomSheetComposeFragment() {
companion object {
const val SUBSCRIPTION_KEY: String = "arg.space.files.subscription.key"
const val SPACE_ID_KEY = "arg.space.files.space.key"
fun args(subscription: Id, space: Id) = bundleOf(
SUBSCRIPTION_KEY to subscription,
SPACE_ID_KEY to space
)
}
}

View file

@ -15,8 +15,10 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_ui.common.ComposeDialogView
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.safeNavigate
import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
import com.anytypeio.anytype.core_utils.intents.SystemAction
@ -37,6 +39,8 @@ class SpacesStorageFragment : BaseBottomSheetComposeFragment() {
private val vm by viewModels<SpacesStorageViewModel> { factory }
private val space get() = arg<Id>(ARG_SPACE_ID_KEY)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -88,7 +92,8 @@ class SpacesStorageFragment : BaseBottomSheetComposeFragment() {
when (command) {
is SpacesStorageViewModel.Command.OpenRemoteFilesManageScreen -> {
openRemoteStorageScreen(
subscription = command.subscription
subscription = command.subscription,
spaceId = space
)
}
is SpacesStorageViewModel.Command.SendGetMoreSpaceEmail -> {
@ -108,11 +113,14 @@ class SpacesStorageFragment : BaseBottomSheetComposeFragment() {
}
}
private fun openRemoteStorageScreen(subscription: String) {
private fun openRemoteStorageScreen(subscription: String, spaceId: Id) {
findNavController().safeNavigate(
R.id.spacesStorageScreen,
R.id.remoteStorageFragment,
bundleOf(RemoteFilesManageFragment.SUBSCRIPTION_KEY to subscription)
args = RemoteFilesManageFragment.args(
subscription = subscription,
space = spaceId
),
)
}
@ -129,12 +137,20 @@ class SpacesStorageFragment : BaseBottomSheetComposeFragment() {
}
override fun injectDependencies() {
componentManager().spacesStorageComponent.get().inject(this)
val vmParams = SpacesStorageViewModel.VmParams(
spaceId = SpaceId(space)
)
componentManager().spacesStorageComponent.get(vmParams).inject(this)
}
override fun releaseDependencies() {
componentManager().spacesStorageComponent.release()
}
companion object {
private const val ARG_SPACE_ID_KEY = "arg.space-storage.space-id"
fun args(space: Id) = bundleOf(ARG_SPACE_ID_KEY to space)
}
}
private const val PADDING_TOP = 54

View file

@ -29,6 +29,7 @@ import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel.Command
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
import com.anytypeio.anytype.ui.multiplayer.LeaveSpaceWarning
import com.anytypeio.anytype.ui.multiplayer.ShareSpaceFragment
import com.anytypeio.anytype.ui.settings.SpacesStorageFragment
import com.anytypeio.anytype.ui.settings.typography
import com.anytypeio.anytype.ui.spaces.DeleteSpaceWarning
import com.anytypeio.anytype.ui_settings.space.SpaceSettingsScreen
@ -69,7 +70,10 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment() {
),
onFileStorageClick = throttledClick(
onClick = {
findNavController().navigate(R.id.spacesStorageScreen)
findNavController().navigate(
resId = R.id.spacesStorageScreen,
args = SpacesStorageFragment.args(space = space)
)
}
),
onPersonalizationClicked = throttledClick(
@ -204,7 +208,8 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment() {
}
override fun injectDependencies() {
componentManager().spaceSettingsComponent.get(SpaceId(space)).inject(this)
val vmParams = SpaceSettingsViewModel.VmParams(space = SpaceId(space))
componentManager().spaceSettingsComponent.get(params = vmParams).inject(this)
}
override fun releaseDependencies() {

View file

@ -22,6 +22,7 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.DateTypeNameProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.`object`.OpenObject
import com.anytypeio.anytype.domain.objects.DeleteObjects
import com.anytypeio.anytype.domain.objects.ObjectStore
@ -32,12 +33,14 @@ import com.anytypeio.anytype.domain.search.ObjectSearchSubscriptionContainer
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.feature_allcontent.presentation.AllContentViewModel
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.presentation.widgets.WidgetDispatchEvent
import com.anytypeio.anytype.presentation.widgets.collection.CollectionViewModel
import com.anytypeio.anytype.ui.settings.RemoteFilesManageFragment
import dagger.Binds
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import dagger.Provides
@ -52,7 +55,10 @@ interface CollectionComponent {
@Component.Factory
interface Factory {
fun create(dependencies: CollectionDependencies): CollectionComponent
fun create(
@BindsInstance vmParams: CollectionViewModel.VmParams,
dependencies: CollectionDependencies
): CollectionComponent
}
fun inject(fragment: CollectionFragment)
@ -224,4 +230,5 @@ interface CollectionDependencies : ComponentDependencies {
fun dateProvider(): DateProvider
fun dateTypeNameProvider(): DateTypeNameProvider
fun analyticsHelperDelegate(): AnalyticSpaceHelperDelegate
fun provideUserPermissionProvider(): UserPermissionProvider
}

View file

@ -14,6 +14,7 @@ import androidx.navigation.fragment.findNavController
import com.anytypeio.anytype.BuildConfig
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.argString
import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
@ -154,7 +155,8 @@ class CollectionFragment : BaseComposeFragment() {
}
override fun injectDependencies() {
componentManager().collectionComponent.get().inject(this)
val vmParams = CollectionViewModel.VmParams(spaceId = SpaceId(space))
componentManager().collectionComponent.get(params = vmParams).inject(this)
}
override fun releaseDependencies() {

View file

@ -63,8 +63,10 @@ import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.colorResource
@ -88,13 +90,12 @@ import com.anytypeio.anytype.core_ui.views.Relations3
import com.anytypeio.anytype.core_ui.views.Title1
import com.anytypeio.anytype.core_ui.views.UXBody
import com.anytypeio.anytype.core_ui.widgets.CollectionActionWidget
import com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
import com.anytypeio.anytype.core_ui.widgets.ListWidgetObjectIcon
import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.setVisible
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.widgets.collection.CollectionObjectView
import com.anytypeio.anytype.presentation.widgets.collection.CollectionUiState
import com.anytypeio.anytype.presentation.widgets.collection.CollectionView
@ -141,7 +142,10 @@ fun ScreenContent(
SearchBar(vm, uiState)
ListView(vm, uiState, stringResource(id = R.string.search_no_results_try))
}
Box(Modifier.align(BottomCenter).padding(bottom = 20.dp)) {
Box(
Modifier
.align(BottomCenter)
.padding(bottom = 20.dp)) {
BottomNavigationMenu(
backClick = { vm.onPrevClicked() },
homeClick = { vm.onHomeClicked() },
@ -181,15 +185,17 @@ fun TopBar(
style = Title1,
color = colorResource(id = R.color.text_primary)
)
Text(
modifier = Modifier
.align(CenterEnd)
.noRippleClickable { vm.onActionClicked() }
.padding(start = 16.dp, top = 12.dp, bottom = 12.dp),
text = uiState.actionName,
style = UXBody,
color = colorResource(id = R.color.glyph_active)
)
if (uiState.isActionButtonVisible) {
Text(
modifier = Modifier
.align(CenterEnd)
.noRippleClickable { vm.onActionClicked() }
.padding(start = 16.dp, top = 12.dp, bottom = 12.dp),
text = uiState.actionName,
style = UXBody,
color = colorResource(id = R.color.glyph_active)
)
}
}
}
@ -240,6 +246,7 @@ fun ListView(
is CollectionView.FavoritesView -> it.obj.id
is SectionView -> it.name
is EmptySearch -> it.query
CollectionView.BinEmpty -> "bin-empty"
}
}
) { item ->
@ -334,6 +341,33 @@ fun ListView(
}
}
}
CollectionView.BinEmpty -> {
Box(
modifier = Modifier.fillParentMaxHeight()
) {
Column(
modifier = Modifier
.align(Alignment.Center)
.padding(horizontal = 16.dp)
) {
Text(
text = stringResource(R.string.bin_empty_title),
style = UXBody,
color = colorResource(id = R.color.text_primary),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
Text(
text = stringResource(R.string.bin_empty_subtitle),
style = UXBody,
color = colorResource(id = R.color.text_secondary),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
}
}
}
}
}
}
@ -399,18 +433,6 @@ fun SearchBar(
}
}
@Composable
fun Icon(icon: ObjectIcon?) {
icon?.let {
AndroidView(factory = { ctx ->
val iconWidget = LayoutInflater.from(ctx)
.inflate(R.layout.collections_icon, null) as ObjectIconWidget
iconWidget.setIcon(it)
iconWidget
})
}
}
@Composable
fun SectionItem(
view: SectionView
@ -444,6 +466,8 @@ fun CollectionItem(
displayType: Boolean,
) {
val haptic = LocalHapticFeedback.current
Box(
Modifier
.fillMaxWidth()
@ -454,7 +478,10 @@ fun CollectionItem(
} else {
Modifier.combinedClickable(
onClick = onClick,
onLongClick = onLongClick
onLongClick = {
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
onLongClick()
}
)
}
)
@ -505,7 +532,7 @@ fun CollectionItem(
.size(48.dp)
.align(CenterVertically)
) {
Icon(icon = view.obj.icon)
ListWidgetObjectIcon(icon = view.obj.icon, modifier = Modifier, iconSize = 48.dp)
}
Column(

View file

@ -457,7 +457,7 @@ class AllContentViewModel(
container = container,
sorts = uiSorts,
types = uiSortTypes,
showBin = permission.value?.isOwnerOrEditor() == true
showBin = true
)
}
}

View file

@ -939,6 +939,9 @@
<string name="log_in">Log In</string>
<string name="create_object_section_library">Anytype Library</string>
<string name="bin_empty_title">Your trash is empty.</string>
<string name="bin_empty_subtitle">Looks like youre all tidy and organized!</string>
<!--region SLASH WIDGET -->

View file

@ -39,7 +39,7 @@ interface AppNavigation {
fun exitToVault()
fun openGlobalSearch(space: Id)
fun openUpdateAppScreen()
fun openRemoteFilesManageScreen(subscription: Id)
fun openRemoteFilesManageScreen(subscription: Id, space: Id)
fun deletedAccountScreen(deadline: Long)
@ -96,8 +96,6 @@ interface AppNavigation {
data class OpenTemplates(val typeId: Id) : Command()
data class OpenLibrary(val space: Id): Command()
data class OpenRemoteFilesManageScreen(val subscription: Id) : Command()
}
interface Provider {

View file

@ -50,6 +50,7 @@ import kotlinx.coroutines.launch
import timber.log.Timber
class SpacesStorageViewModel(
private val vmParams: VmParams,
private val analytics: Analytics,
private val spaceManager: SpaceManager,
private val appCoroutineDispatchers: AppCoroutineDispatchers,
@ -88,7 +89,12 @@ class SpacesStorageViewModel(
private suspend fun dispatchCommand(event: Event) {
when (event) {
Event.OnManageFilesClicked -> {
commands.emit(Command.OpenRemoteFilesManageScreen(Subscription.Files.id))
commands.emit(
Command.OpenRemoteFilesManageScreen(
subscription = Subscription.Files.id,
space = vmParams.spaceId
)
)
analytics.sendSettingsSpaceStorageManageEvent()
}
Event.OnGetMoreSpaceClicked -> {
@ -169,7 +175,7 @@ class SpacesStorageViewModel(
val percentUsage = calculatePercentUsage(bytesUsage, bytesLimit)
val isShowGetMoreSpace = isNeedToShowGetMoreSpace(percentUsage, localUsage, bytesLimit)
val isShowSpaceUsedWarning = isShowSpaceUsedWarning(percentUsage)
val activeSpaceId = spaceManager.get()
val activeSpaceId = vmParams.spaceId.id
val activeSpace = spaces.firstOrNull { it.targetSpaceId == activeSpaceId }
val segmentLegendItems = getSegmentLegendItems(nodeUsageInfo, activeSpace)
@ -318,8 +324,8 @@ class SpacesStorageViewModel(
activeSpace: ObjectWrapper.Basic?
): List<SegmentLegendItem> {
val result = mutableListOf<SegmentLegendItem>()
val currentSpace = nodeUsageInfo.spaces.firstOrNull { it.space == spaceManager.get() }
val otherSpaces = nodeUsageInfo.spaces.filter { it.space != spaceManager.get() }
val currentSpace = nodeUsageInfo.spaces.firstOrNull { it.space == vmParams.spaceId.id }
val otherSpaces = nodeUsageInfo.spaces.filter { it.space != vmParams.spaceId.id }
var otherSpacesUsages = 0L
otherSpaces.forEach { spaceUsage ->
otherSpacesUsages += spaceUsage.bytesUsage
@ -410,7 +416,7 @@ class SpacesStorageViewModel(
}
sealed class Command {
data class OpenRemoteFilesManageScreen(val subscription: Id) : Command()
data class OpenRemoteFilesManageScreen(val subscription: Id, val space: SpaceId) : Command()
data class SendGetMoreSpaceEmail(val account: Id, val name: String, val limit: String) :
Command()
data object ShowMembershipScreen : Command()
@ -422,6 +428,10 @@ class SpacesStorageViewModel(
data class Success(val tierId: TierId) : ActiveTierState()
}
data class VmParams(
val spaceId: SpaceId
)
companion object {
private const val SPACES_STORAGE_SUBSCRIPTION_ID = "spaces_storage_view_model_subscription"
}

View file

@ -14,6 +14,7 @@ import com.anytypeio.anytype.presentation.membership.provider.MembershipProvider
import javax.inject.Inject
class SpacesStorageViewModelFactory @Inject constructor(
private val vmParams: SpacesStorageViewModel.VmParams,
private val analytics: Analytics,
private val spaceManager: SpaceManager,
private val appCoroutineDispatchers: AppCoroutineDispatchers,
@ -36,6 +37,7 @@ class SpacesStorageViewModelFactory @Inject constructor(
storelessSubscriptionContainer = storelessSubscriptionContainer,
getAccount = getAccount,
membershipProvider = membershipProvider,
userPermissionProvider = userPermissionProvider
userPermissionProvider = userPermissionProvider,
vmParams = vmParams
) as T
}

View file

@ -28,8 +28,6 @@ import com.anytypeio.anytype.core_utils.ui.ViewState
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.debugging.DebugSpaceShareDownloader
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.icon.SetImageIcon
import com.anytypeio.anytype.domain.media.UploadFile
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
@ -49,7 +47,7 @@ import kotlinx.coroutines.launch
import timber.log.Timber
class SpaceSettingsViewModel(
private val params: Params,
private val params: VmParams,
private val analytics: Analytics,
private val setSpaceDetails: SetSpaceDetails,
private val spaceManager: SpaceManager,
@ -401,7 +399,7 @@ class SpaceSettingsViewModel(
}
class Factory @Inject constructor(
private val params: Params,
private val params: VmParams,
private val analytics: Analytics,
private val container: SpaceViewSubscriptionContainer,
private val urlBuilder: UrlBuilder,
@ -439,7 +437,7 @@ class SpaceSettingsViewModel(
) as T
}
class Params(val space: SpaceId)
data class VmParams(val space: SpaceId)
companion object {
const val SPACE_DEBUG_MSG = "Kindly share this debug logs with Anytype developers."

View file

@ -12,5 +12,6 @@ class CollectionUiState(
val objectActions: List<ObjectAction>,
val inDragMode: Boolean,
val displayType: Boolean,
val operationInProgress: Boolean
val operationInProgress: Boolean,
val isActionButtonVisible: Boolean
)

View file

@ -16,6 +16,7 @@ import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Position
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.ext.process
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.ext.cancel
import com.anytypeio.anytype.core_utils.ext.replace
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
@ -33,6 +34,7 @@ import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.DateTypeNameProvider
import com.anytypeio.anytype.domain.misc.Reducer
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.`object`.OpenObject
import com.anytypeio.anytype.domain.objects.DeleteObjects
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
@ -86,6 +88,7 @@ import timber.log.Timber
import com.anytypeio.anytype.core_models.ObjectView as CoreObjectView
class CollectionViewModel(
private val vmParams: VmParams,
private val container: StorelessSubscriptionContainer,
private val urlBuilder: UrlBuilder,
private val getObjectTypes: GetObjectTypes,
@ -106,16 +109,20 @@ class CollectionViewModel(
private val spaceManager: SpaceManager,
private val getSpaceView: GetSpaceView,
private val dateTypeNameProvider: DateTypeNameProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
private val userPermissionProvider: UserPermissionProvider
) : ViewModel(), Reducer<CoreObjectView, Payload>, AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val payloads: Flow<Payload>
val icon = MutableStateFlow<ProfileIconView>(ProfileIconView.Loading)
private val permission = MutableStateFlow(userPermissionProvider.get(vmParams.spaceId))
init {
Timber.i("CollectionViewModel, init")
Timber.i("CollectionViewModel, init, spaceId:${vmParams.spaceId.id}")
proceedWithObservingProfileIcon()
proceedWithObservingPermissions()
val externalChannelEvents: Flow<Payload> = spaceManager
.observe()
.flatMapLatest { config ->
@ -166,7 +173,8 @@ class CollectionViewModel(
objectActions = actionObjectFilter.filter(subscription, selectedViews()),
inDragMode = subscription == Subscription.Favorites && mode == InteractionMode.Edit,
displayType = subscription != Subscription.Sets || subscription != Subscription.Files,
operationInProgress = operationInProgress
operationInProgress = operationInProgress,
isActionButtonVisible = permission.value?.isOwnerOrEditor() == true
)
)
}.stateIn(
@ -175,6 +183,16 @@ class CollectionViewModel(
initialValue = Resultat.loading()
)
private fun proceedWithObservingPermissions() {
viewModelScope.launch {
userPermissionProvider
.observe(space = vmParams.spaceId)
.collect {
permission.value = it
}
}
}
private fun proceedWithObservingProfileIcon() {
viewModelScope.launch {
spaceManager
@ -207,7 +225,7 @@ class CollectionViewModel(
val params = GetObjectTypes.Params(
sorts = emptyList(),
filters = ObjectSearchConstants.filterTypes(
spaces = listOf(spaceManager.get())
spaces = listOf(vmParams.spaceId.id)
),
keys = ObjectSearchConstants.defaultKeysObjectType
)
@ -238,7 +256,7 @@ class CollectionViewModel(
fun onStart(subscription: Subscription) {
val isFirstLaunch = this.subscription == Subscription.None
this.subscription = subscription
if (isFirstLaunch && (subscription == Subscription.Bin || subscription == Subscription.Files)) {
if (permission.value?.isOwnerOrEditor() == true && isFirstLaunch && (subscription == Subscription.Bin || subscription == Subscription.Files)) {
onStartEditMode()
}
subscribeObjects()
@ -248,7 +266,7 @@ class CollectionViewModel(
return StoreSearchParams(
subscription = subscription.id,
keys = subscription.keys,
filters = subscription.space(spaceManager.get()),
filters = subscription.space(vmParams.spaceId.id),
sorts = subscription.sorts,
limit = subscription.limit
)
@ -324,16 +342,23 @@ class CollectionViewModel(
container.subscribe(params).map { results -> results.distinctBy { it.id } },
queryFlow(),
objectTypes()
) { objs, query, types ->
val result = objs.filter { obj ->
obj.getProperName().contains(query, true)
}.toViews(urlBuilder, types)
) { objects, query, types ->
val filteredResults = objects.filter { obj ->
obj.getProperName().contains(query, ignoreCase = true)
}
val views = filteredResults
.toViews(urlBuilder = urlBuilder, objectTypes = types)
.map { ObjectView(it) }
.tryAddSections()
if (result.isEmpty() && query.isNotEmpty())
listOf(CollectionView.EmptySearch(query))
else
result
when {
views.isNotEmpty() -> views
subscription == Subscription.Bin && query.isEmpty() -> listOf(CollectionView.BinEmpty)
query.isNotEmpty() -> listOf(CollectionView.EmptySearch(query))
else -> emptyList()
}
}.catch {
Timber.e(it, "Error in subscription flow")
}
@ -457,6 +482,10 @@ class CollectionViewModel(
}
fun onObjectLongClicked(view: CollectionObjectView) {
if (permission.value?.isOwnerOrEditor() != true) {
Timber.w("User has no permission to edit Collection Screen")
return
}
if (interactionMode.value != InteractionMode.Edit) {
interactionMode.value = InteractionMode.Edit
}
@ -862,7 +891,7 @@ class CollectionViewModel(
startTime = startTime,
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key),
view = EventsDictionary.View.viewHome,
spaceParams = provideParams(spaceManager.get())
spaceParams = provideParams(vmParams.spaceId.id)
)
proceedWithOpeningObject(result.obj)
},
@ -927,7 +956,10 @@ class CollectionViewModel(
super.onCleared()
}
data class VmParams(val spaceId: SpaceId)
class Factory @Inject constructor(
private val vmParams: VmParams,
private val container: StorelessSubscriptionContainer,
private val urlBuilder: UrlBuilder,
private val getObjectTypes: GetObjectTypes,
@ -948,7 +980,8 @@ class CollectionViewModel(
private val spaceManager: SpaceManager,
private val getSpaceView: GetSpaceView,
private val dateTypeNameProvider: DateTypeNameProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
private val userPermissionProvider: UserPermissionProvider
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -974,7 +1007,9 @@ class CollectionViewModel(
spaceManager = spaceManager,
getSpaceView = getSpaceView,
dateTypeNameProvider = dateTypeNameProvider,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
userPermissionProvider = userPermissionProvider,
vmParams = vmParams
) as T
}
}

View file

@ -26,4 +26,6 @@ sealed class CollectionView {
) : CollectionView()
data class EmptySearch(val query: String) : CollectionView()
data object BinEmpty : CollectionView()
}