mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3044 Chats | Enhancement | Space-level chat basics (#1794)
This commit is contained in:
parent
ee565a57f0
commit
047a071f85
21 changed files with 438 additions and 131 deletions
|
@ -28,4 +28,7 @@ class DefaultFeatureToggles @Inject constructor(
|
|||
|
||||
override val isSpaceLevelChatEnabled: Boolean
|
||||
get() = true
|
||||
|
||||
override val isNewSpaceHomeEnabled: Boolean
|
||||
get() = true
|
||||
}
|
|
@ -49,6 +49,7 @@ import com.anytypeio.anytype.di.feature.ViewerSortModule
|
|||
import com.anytypeio.anytype.di.feature.auth.DaggerDeletedAccountComponent
|
||||
import com.anytypeio.anytype.di.feature.cover.UnsplashModule
|
||||
import com.anytypeio.anytype.di.feature.discussions.DaggerDiscussionComponent
|
||||
import com.anytypeio.anytype.di.feature.discussions.DaggerSpaceLevelChatComponent
|
||||
import com.anytypeio.anytype.di.feature.gallery.DaggerGalleryInstallationComponent
|
||||
import com.anytypeio.anytype.di.feature.home.DaggerHomeScreenComponent
|
||||
import com.anytypeio.anytype.di.feature.membership.DaggerMembershipComponent
|
||||
|
@ -99,6 +100,7 @@ import com.anytypeio.anytype.di.feature.widgets.DaggerSelectWidgetSourceComponen
|
|||
import com.anytypeio.anytype.di.feature.widgets.DaggerSelectWidgetTypeComponent
|
||||
import com.anytypeio.anytype.di.main.MainComponent
|
||||
import com.anytypeio.anytype.feature_allcontent.presentation.AllContentViewModel
|
||||
import com.anytypeio.anytype.feature_discussions.presentation.DiscussionViewModel
|
||||
import com.anytypeio.anytype.gallery_experience.viewmodel.GalleryInstallationViewModel
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.EditorViewModel
|
||||
|
@ -1051,7 +1053,7 @@ class ComponentManager(
|
|||
.build()
|
||||
}
|
||||
|
||||
val discussionComponent = ComponentMapWithParam { params: BaseViewModel.DefaultParams ->
|
||||
val discussionComponent = ComponentMapWithParam { params: DiscussionViewModel.Params ->
|
||||
DaggerDiscussionComponent
|
||||
.builder()
|
||||
.withDependencies(findComponentDependencies())
|
||||
|
@ -1059,6 +1061,14 @@ class ComponentManager(
|
|||
.build()
|
||||
}
|
||||
|
||||
val spaceLevelChatComponent = ComponentMapWithParam { params: DiscussionViewModel.Params ->
|
||||
DaggerSpaceLevelChatComponent
|
||||
.builder()
|
||||
.withDependencies(findComponentDependencies())
|
||||
.withParams(params)
|
||||
.build()
|
||||
}
|
||||
|
||||
val vaultComponent = Component {
|
||||
DaggerVaultComponent
|
||||
.factory()
|
||||
|
|
|
@ -151,7 +151,7 @@ class DiscussionFragment : BaseComposeFragment() {
|
|||
.discussionComponent
|
||||
.get(
|
||||
key = ctx,
|
||||
param = BaseViewModel.DefaultParams(
|
||||
param = DiscussionViewModel.Params.Default(
|
||||
ctx = ctx,
|
||||
space = SpaceId(space)
|
||||
)
|
||||
|
|
|
@ -14,10 +14,13 @@ import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
|||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.feature_discussions.presentation.DiscussionViewModel
|
||||
import com.anytypeio.anytype.feature_discussions.presentation.DiscussionViewModelFactory
|
||||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.ui.home.HomeScreenFragment
|
||||
import dagger.Binds
|
||||
import dagger.BindsInstance
|
||||
import dagger.Component
|
||||
|
@ -35,13 +38,33 @@ interface DiscussionComponent {
|
|||
@Component.Builder
|
||||
interface Builder {
|
||||
@BindsInstance
|
||||
fun withParams(params: BaseViewModel.DefaultParams): Builder
|
||||
fun withParams(params: DiscussionViewModel.Params): Builder
|
||||
fun withDependencies(dependencies: DiscussionComponentDependencies): Builder
|
||||
fun build(): DiscussionComponent
|
||||
}
|
||||
fun inject(fragment: DiscussionFragment)
|
||||
}
|
||||
|
||||
@Component(
|
||||
dependencies = [DiscussionComponentDependencies::class],
|
||||
modules = [
|
||||
DiscussionModule::class,
|
||||
DiscussionModule.Declarations::class
|
||||
]
|
||||
)
|
||||
@PerScreen
|
||||
interface SpaceLevelChatComponent {
|
||||
@Component.Builder
|
||||
interface Builder {
|
||||
@BindsInstance
|
||||
fun withParams(params: DiscussionViewModel.Params): Builder
|
||||
fun withDependencies(dependencies: DiscussionComponentDependencies): Builder
|
||||
fun build(): SpaceLevelChatComponent
|
||||
}
|
||||
|
||||
fun getViewModel(): DiscussionViewModel
|
||||
}
|
||||
|
||||
@Module
|
||||
object DiscussionModule {
|
||||
@Module
|
||||
|
@ -51,7 +74,6 @@ object DiscussionModule {
|
|||
fun bindViewModelFactory(
|
||||
factory: DiscussionViewModelFactory
|
||||
): ViewModelProvider.Factory
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,4 +90,5 @@ interface DiscussionComponentDependencies : ComponentDependencies {
|
|||
fun chatEventChannel(): ChatEventChannel
|
||||
fun logger(): Logger
|
||||
fun members(): ActiveSpaceMemberSubscriptionContainer
|
||||
fun spaceViewSubscriptionContainer(): SpaceViewSubscriptionContainer
|
||||
}
|
|
@ -67,7 +67,6 @@ import kotlinx.coroutines.Dispatchers
|
|||
)
|
||||
@PerScreen
|
||||
interface HomeScreenComponent {
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
fun create(dependencies: HomeScreenDependencies): HomeScreenComponent
|
||||
|
|
|
@ -72,6 +72,7 @@ import org.burnoutcrew.reorderable.reorderable
|
|||
|
||||
@Composable
|
||||
fun HomeScreen(
|
||||
modifier: Modifier,
|
||||
mode: InteractionMode,
|
||||
widgets: List<WidgetView>,
|
||||
onExpand: (TreePath) -> Unit,
|
||||
|
@ -98,7 +99,7 @@ fun HomeScreen(
|
|||
onBackLongClicked: () -> Unit
|
||||
) {
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Box(modifier = modifier.fillMaxSize()) {
|
||||
WidgetList(
|
||||
widgets = widgets,
|
||||
onExpand = onExpand,
|
||||
|
|
|
@ -4,10 +4,18 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
@ -21,12 +29,16 @@ import androidx.navigation.fragment.findNavController
|
|||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.primitives.Space
|
||||
import com.anytypeio.anytype.core_ui.extensions.throttledClick
|
||||
import com.anytypeio.anytype.core_utils.ext.arg
|
||||
import com.anytypeio.anytype.core_utils.ext.argOrNull
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseComposeFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.ext.daggerViewModel
|
||||
import com.anytypeio.anytype.feature_discussions.presentation.DiscussionViewModel
|
||||
import com.anytypeio.anytype.feature_discussions.ui.DiscussionScreenWrapper
|
||||
import com.anytypeio.anytype.other.DefaultDeepLinkResolver
|
||||
import com.anytypeio.anytype.presentation.home.Command
|
||||
|
@ -40,9 +52,9 @@ import com.anytypeio.anytype.ui.multiplayer.ShareSpaceFragment
|
|||
import com.anytypeio.anytype.ui.objects.creation.ObjectTypeSelectionFragment
|
||||
import com.anytypeio.anytype.ui.objects.creation.WidgetObjectTypeFragment
|
||||
import com.anytypeio.anytype.ui.objects.creation.WidgetSourceTypeFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.ObjectTypeSelectionListener
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.WidgetObjectTypeListener
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.WidgetSourceTypeListener
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.ObjectTypeSelectionListener
|
||||
import com.anytypeio.anytype.ui.payments.MembershipFragment
|
||||
import com.anytypeio.anytype.ui.settings.space.SpaceSettingsFragment
|
||||
import com.anytypeio.anytype.ui.settings.typography
|
||||
|
@ -59,8 +71,10 @@ class HomeScreenFragment : BaseComposeFragment(),
|
|||
|
||||
private val deepLink: String? get() = argOrNull(DEEP_LINK_KEY)
|
||||
|
||||
private val space: Id get() = arg<Id>(SPACE_ID_KEY)
|
||||
|
||||
private var isMnemonicReminderDialogNeeded: Boolean
|
||||
get() = argOrNull<Boolean>(SHOW_MNEMONIC_KEY) ?: false
|
||||
get() = argOrNull<Boolean>(SHOW_MNEMONIC_KEY) == true
|
||||
set(value) { arguments?.putBoolean(SHOW_MNEMONIC_KEY, value) }
|
||||
|
||||
|
||||
|
@ -86,42 +100,88 @@ class HomeScreenFragment : BaseComposeFragment(),
|
|||
surface = colorResource(id = R.color.background_secondary)
|
||||
)
|
||||
) {
|
||||
HomeScreen(
|
||||
widgets = vm.views.collectAsState().value,
|
||||
mode = vm.mode.collectAsState().value,
|
||||
onExpand = { path -> vm.onExpand(path) },
|
||||
onCreateWidget = vm::onCreateWidgetClicked,
|
||||
onEditWidgets = vm::onEditWidgets,
|
||||
onExitEditMode = vm::onExitEditMode,
|
||||
onWidgetMenuAction = { widget: Id, action: DropDownMenuAction ->
|
||||
vm.onDropDownMenuAction(widget, action)
|
||||
},
|
||||
onWidgetObjectClicked = vm::onWidgetObjectClicked,
|
||||
onWidgetSourceClicked = vm::onWidgetSourceClicked,
|
||||
onChangeWidgetView = vm::onChangeCurrentWidgetView,
|
||||
onToggleExpandedWidgetState = vm::onToggleCollapsedWidgetState,
|
||||
onSearchClicked = vm::onSearchIconClicked,
|
||||
onCreateNewObjectClicked = throttledClick(
|
||||
onClick = { vm.onCreateNewObjectClicked() }
|
||||
),
|
||||
onCreateNewObjectLongClicked = throttledClick(
|
||||
onClick = { vm.onCreateNewObjectLongClicked() }
|
||||
),
|
||||
onBackClicked = throttledClick(
|
||||
onClick = vm::onBackClicked
|
||||
),
|
||||
onSpaceWidgetClicked = throttledClick(
|
||||
onClick = vm::onSpaceSettingsClicked
|
||||
),
|
||||
onBundledWidgetClicked = vm::onBundledWidgetClicked,
|
||||
onMove = vm::onMove,
|
||||
onObjectCheckboxClicked = vm::onObjectCheckboxClicked,
|
||||
onSpaceShareIconClicked = vm::onSpaceShareIconClicked,
|
||||
onSeeAllObjectsClicked = vm::onSeeAllObjectsClicked,
|
||||
onCreateObjectInsideWidget = vm::onCreateObjectInsideWidget,
|
||||
onCreateDataViewObject = vm::onCreateDataViewObject,
|
||||
onBackLongClicked = vm::onBackLongClicked
|
||||
)
|
||||
val focus = LocalFocusManager.current
|
||||
val component = componentManager().spaceLevelChatComponent
|
||||
val spaceLevelChatViewModel = daggerViewModel {
|
||||
component.get(
|
||||
key = space,
|
||||
param = DiscussionViewModel.Params.SpaceLevelChat(
|
||||
space = Space(space)
|
||||
)
|
||||
).getViewModel()
|
||||
}
|
||||
val pagerState = rememberPagerState { 2 }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
Box(
|
||||
Modifier.fillMaxSize()
|
||||
) {
|
||||
HomeScreenToolbar(
|
||||
onWidgetTabClicked = {
|
||||
coroutineScope.launch {
|
||||
pagerState.animateScrollToPage(0)
|
||||
}
|
||||
},
|
||||
onChatTabClicked = {
|
||||
coroutineScope.launch {
|
||||
pagerState.animateScrollToPage(1)
|
||||
}
|
||||
}
|
||||
)
|
||||
HorizontalPager(
|
||||
modifier = Modifier.padding(top = 64.dp),
|
||||
state = pagerState,
|
||||
userScrollEnabled = false
|
||||
) { page ->
|
||||
if (page == 0) {
|
||||
focus.clearFocus(force = true)
|
||||
HomeScreen(
|
||||
modifier = Modifier,
|
||||
widgets = vm.views.collectAsState().value,
|
||||
mode = vm.mode.collectAsState().value,
|
||||
onExpand = { path -> vm.onExpand(path) },
|
||||
onCreateWidget = vm::onCreateWidgetClicked,
|
||||
onEditWidgets = vm::onEditWidgets,
|
||||
onExitEditMode = vm::onExitEditMode,
|
||||
onWidgetMenuAction = { widget: Id, action: DropDownMenuAction ->
|
||||
vm.onDropDownMenuAction(widget, action)
|
||||
},
|
||||
onWidgetObjectClicked = vm::onWidgetObjectClicked,
|
||||
onWidgetSourceClicked = vm::onWidgetSourceClicked,
|
||||
onChangeWidgetView = vm::onChangeCurrentWidgetView,
|
||||
onToggleExpandedWidgetState = vm::onToggleCollapsedWidgetState,
|
||||
onSearchClicked = vm::onSearchIconClicked,
|
||||
onCreateNewObjectClicked = throttledClick(
|
||||
onClick = { vm.onCreateNewObjectClicked() }
|
||||
),
|
||||
onCreateNewObjectLongClicked = throttledClick(
|
||||
onClick = { vm.onCreateNewObjectLongClicked() }
|
||||
),
|
||||
onBackClicked = throttledClick(
|
||||
onClick = vm::onBackClicked
|
||||
),
|
||||
onSpaceWidgetClicked = throttledClick(
|
||||
onClick = vm::onSpaceSettingsClicked
|
||||
),
|
||||
onBundledWidgetClicked = vm::onBundledWidgetClicked,
|
||||
onMove = vm::onMove,
|
||||
onObjectCheckboxClicked = vm::onObjectCheckboxClicked,
|
||||
onSpaceShareIconClicked = vm::onSpaceShareIconClicked,
|
||||
onSeeAllObjectsClicked = vm::onSeeAllObjectsClicked,
|
||||
onCreateObjectInsideWidget = vm::onCreateObjectInsideWidget,
|
||||
onCreateDataViewObject = vm::onCreateDataViewObject,
|
||||
onBackLongClicked = vm::onBackLongClicked
|
||||
)
|
||||
} else {
|
||||
DiscussionScreenWrapper(
|
||||
isSpaceLevelChat = true,
|
||||
vm = spaceLevelChatViewModel,
|
||||
onAttachClicked = {
|
||||
// TODO
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -377,17 +437,28 @@ class HomeScreenFragment : BaseComposeFragment(),
|
|||
|
||||
override fun injectDependencies() {
|
||||
componentManager().homeScreenComponent.get().inject(this)
|
||||
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().homeScreenComponent.release()
|
||||
}
|
||||
|
||||
override fun onApplyWindowRootInsets(view: View) {
|
||||
super.onApplyWindowRootInsets(view)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SHOW_MNEMONIC_KEY = "arg.home-screen.show-mnemonic"
|
||||
const val DEEP_LINK_KEY = "arg.home-screen.deep-link"
|
||||
fun args(deeplink: String?) : Bundle = bundleOf(
|
||||
DEEP_LINK_KEY to deeplink
|
||||
const val SPACE_ID_KEY = "arg.home-screen.space-id"
|
||||
|
||||
fun args(
|
||||
space: Id,
|
||||
deeplink: String?
|
||||
) : Bundle = bundleOf(
|
||||
DEEP_LINK_KEY to deeplink,
|
||||
SPACE_ID_KEY to space
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.anytypeio.anytype.ui.home
|
||||
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
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.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.feature_discussions.R
|
||||
|
||||
@Composable
|
||||
fun HomeScreenToolbar(
|
||||
onWidgetTabClicked: () -> Unit,
|
||||
onChatTabClicked: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(64.dp)
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_home_toolbar_widgets),
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.align(Alignment.CenterStart)
|
||||
.noRippleClickable {
|
||||
onWidgetTabClicked()
|
||||
},
|
||||
contentDescription = "Widgets button"
|
||||
)
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_home_toolbar_chat),
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.align(Alignment.CenterEnd)
|
||||
.noRippleClickable {
|
||||
onChatTabClicked()
|
||||
},
|
||||
contentDescription = "Chats button"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultPreviews
|
||||
@Composable
|
||||
fun HomeScreenToolbarPreview() {
|
||||
HomeScreenToolbar(
|
||||
onWidgetTabClicked = {},
|
||||
onChatTabClicked = {}
|
||||
)
|
||||
}
|
|
@ -20,6 +20,7 @@ import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
|||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.spaces.Command
|
||||
import com.anytypeio.anytype.presentation.spaces.SelectSpaceViewModel
|
||||
import com.anytypeio.anytype.ui.home.HomeScreenFragment
|
||||
import com.anytypeio.anytype.ui.settings.typography
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -84,7 +85,13 @@ class SelectSpaceFragment : BaseBottomSheetComposeFragment() {
|
|||
is Command.SwitchToNewSpace -> {
|
||||
runCatching {
|
||||
findNavController().popBackStack(R.id.vaultScreen, false)
|
||||
findNavController().navigate(R.id.actionOpenSpaceFromVault)
|
||||
findNavController().navigate(
|
||||
R.id.actionOpenSpaceFromVault,
|
||||
HomeScreenFragment.args(
|
||||
space = command.space.id,
|
||||
deeplink = null
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,10 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>(R.layout.fragment_spl
|
|||
)
|
||||
findNavController().navigate(
|
||||
R.id.actionOpenSpaceFromVault,
|
||||
args = HomeScreenFragment.args(deeplink = command.deeplink)
|
||||
args = HomeScreenFragment.args(
|
||||
deeplink = command.deeplink,
|
||||
space = command.space
|
||||
)
|
||||
)
|
||||
}.onFailure {
|
||||
Timber.e(it, "Error while navigating to widgets from splash")
|
||||
|
@ -119,7 +122,7 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>(R.layout.fragment_spl
|
|||
try {
|
||||
findNavController().navigate(
|
||||
resId = R.id.actionOpenVaultFromSplash,
|
||||
args = HomeScreenFragment.args(deeplink = command.deeplink)
|
||||
args = VaultFragment.args(deeplink = command.deeplink)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error while opening dashboard from splash screen")
|
||||
|
@ -129,7 +132,13 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>(R.layout.fragment_spl
|
|||
is SplashViewModel.Command.NavigateToObject -> {
|
||||
runCatching {
|
||||
findNavController().navigate(R.id.actionOpenVaultFromSplash)
|
||||
findNavController().navigate(R.id.actionOpenSpaceFromVault)
|
||||
findNavController().navigate(
|
||||
R.id.actionOpenSpaceFromVault,
|
||||
args = HomeScreenFragment.args(
|
||||
space = command.space,
|
||||
deeplink = null
|
||||
)
|
||||
)
|
||||
findNavController().navigate(
|
||||
resId = R.id.objectNavigation,
|
||||
args = EditorFragment.args(
|
||||
|
@ -144,7 +153,13 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>(R.layout.fragment_spl
|
|||
is SplashViewModel.Command.NavigateToObjectSet -> {
|
||||
runCatching {
|
||||
findNavController().navigate(R.id.actionOpenVaultFromSplash)
|
||||
findNavController().navigate(R.id.actionOpenSpaceFromVault)
|
||||
findNavController().navigate(
|
||||
R.id.actionOpenSpaceFromVault,
|
||||
args = HomeScreenFragment.args(
|
||||
space = command.space,
|
||||
deeplink = null
|
||||
)
|
||||
)
|
||||
findNavController().navigate(
|
||||
resId = R.id.dataViewNavigation,
|
||||
args = ObjectSetFragment.args(
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.anytypeio.anytype.presentation.vault.VaultViewModel.Navigation
|
|||
import com.anytypeio.anytype.presentation.vault.VaultViewModel.Command
|
||||
import com.anytypeio.anytype.ui.base.navigation
|
||||
import com.anytypeio.anytype.ui.gallery.GalleryInstallationFragment
|
||||
import com.anytypeio.anytype.ui.home.HomeScreenFragment
|
||||
import com.anytypeio.anytype.ui.multiplayer.RequestJoinSpaceFragment
|
||||
import com.anytypeio.anytype.ui.payments.MembershipFragment
|
||||
import com.anytypeio.anytype.ui.settings.ProfileSettingsFragment
|
||||
|
@ -72,7 +73,13 @@ class VaultFragment : BaseComposeFragment() {
|
|||
when (command) {
|
||||
is Command.EnterSpaceHomeScreen -> {
|
||||
runCatching {
|
||||
findNavController().navigate(R.id.actionOpenSpaceFromVault)
|
||||
findNavController().navigate(
|
||||
R.id.actionOpenSpaceFromVault,
|
||||
HomeScreenFragment.args(
|
||||
space = command.space.id,
|
||||
deeplink = null
|
||||
)
|
||||
)
|
||||
}.onFailure {
|
||||
Timber.e(it, "Error while opening space from vault")
|
||||
}
|
||||
|
|
9
core-ui/src/main/res/drawable/ic_home_toolbar_chat.xml
Normal file
9
core-ui/src/main/res/drawable/ic_home_toolbar_chat.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
<path
|
||||
android:pathData="M9.841,26C8.094,26 8.881,25.364 9.259,24.859C9.628,24.354 9.598,24.296 10.141,23.367C10.219,23.216 10.17,23.064 10.025,22.983C6.911,21.247 5,18.409 5,15.178C5,10.099 9.889,6 16,6C22.111,6 27,10.099 27,15.178C27,20.207 22.363,24.347 15.37,24.347C15.243,24.347 15.117,24.337 14.991,24.326C14.855,24.326 14.72,24.377 14.555,24.498C12.906,25.474 11.005,26 9.841,26Z"
|
||||
android:fillColor="@color/glyph_button" />
|
||||
</vector>
|
10
core-ui/src/main/res/drawable/ic_home_toolbar_widgets.xml
Normal file
10
core-ui/src/main/res/drawable/ic_home_toolbar_widgets.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
<path
|
||||
android:pathData="M5,8C5,6.895 5.895,6 7,6H25C26.105,6 27,6.895 27,8C27,9.105 26.105,10 25,10H7C5.895,10 5,9.105 5,8ZM5,24C5,22.895 5.895,22 7,22H25C26.105,22 27,22.895 27,24C27,25.105 26.105,26 25,26H7C5.895,26 5,25.105 5,24ZM7,12C5.895,12 5,12.895 5,14V18C5,19.105 5.895,20 7,20H25C26.105,20 27,19.105 27,18V14C27,12.895 26.105,12 25,12H7Z"
|
||||
android:fillColor="@color/glyph_button"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -17,4 +17,6 @@ interface FeatureToggles {
|
|||
val enableDiscussionDemo: Boolean
|
||||
|
||||
val isSpaceLevelChatEnabled: Boolean
|
||||
|
||||
val isNewSpaceHomeEnabled: Boolean
|
||||
}
|
|
@ -6,6 +6,8 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.chats.Chat
|
||||
import com.anytypeio.anytype.core_models.primitives.Space
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.auth.interactor.GetAccount
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.base.onFailure
|
||||
|
@ -18,11 +20,13 @@ import com.anytypeio.anytype.domain.chats.ToggleChatMessageReaction
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer.Store
|
||||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.`object`.OpenObject
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
|
||||
import com.anytypeio.anytype.presentation.search.GlobalSearchItemView
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
@ -30,8 +34,8 @@ import kotlinx.coroutines.flow.onEach
|
|||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class DiscussionViewModel(
|
||||
private val params: DefaultParams,
|
||||
class DiscussionViewModel @Inject constructor(
|
||||
private val vmParams: Params,
|
||||
private val setObjectDetails: SetObjectDetails,
|
||||
private val openObject: OpenObject,
|
||||
private val chatContainer: ChatContainer,
|
||||
|
@ -41,7 +45,8 @@ class DiscussionViewModel(
|
|||
private val toggleChatMessageReaction: ToggleChatMessageReaction,
|
||||
private val members: ActiveSpaceMemberSubscriptionContainer,
|
||||
private val getAccount: GetAccount,
|
||||
private val urlBuilder: UrlBuilder
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val spaceViews: SpaceViewSubscriptionContainer
|
||||
) : BaseViewModel() {
|
||||
|
||||
val name = MutableStateFlow<String?>(null)
|
||||
|
@ -51,43 +56,65 @@ class DiscussionViewModel(
|
|||
val navigation = MutableSharedFlow<OpenObjectNavigation>()
|
||||
val chatBoxMode = MutableStateFlow<ChatBoxMode>(ChatBoxMode.Default)
|
||||
|
||||
var chat: Id = ""
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
val account = requireNotNull(getAccount.async(Unit).getOrNull())
|
||||
openObject.async(
|
||||
OpenObject.Params(
|
||||
spaceId = params.space,
|
||||
obj = params.ctx,
|
||||
saveAsLastOpened = false
|
||||
)
|
||||
).fold(
|
||||
onSuccess = { obj ->
|
||||
val root = ObjectWrapper.Basic(obj.details[params.ctx].orEmpty())
|
||||
name.value = root.name
|
||||
proceedWithObservingChatMessages(
|
||||
account = account.id
|
||||
when (vmParams) {
|
||||
is Params.Default -> {
|
||||
chat = vmParams.ctx
|
||||
openObject.async(
|
||||
OpenObject.Params(
|
||||
spaceId = vmParams.space,
|
||||
obj = vmParams.ctx,
|
||||
saveAsLastOpened = false
|
||||
)
|
||||
).fold(
|
||||
onSuccess = { obj ->
|
||||
val root = ObjectWrapper.Basic(obj.details[vmParams.ctx].orEmpty())
|
||||
name.value = root.name
|
||||
proceedWithObservingChatMessages(
|
||||
account = account.id,
|
||||
chat = vmParams.ctx
|
||||
)
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while opening chat object")
|
||||
}
|
||||
)
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while opening chat object")
|
||||
}
|
||||
)
|
||||
|
||||
is Params.SpaceLevelChat -> {
|
||||
val targetSpaceView = spaceViews.get(vmParams.space)
|
||||
val spaceLevelChat = targetSpaceView?.getValue<Id>(Relations.CHAT_ID)
|
||||
if (spaceLevelChat != null) {
|
||||
chat = spaceLevelChat
|
||||
proceedWithObservingChatMessages(
|
||||
account = account.id,
|
||||
chat = spaceLevelChat
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun proceedWithObservingChatMessages(
|
||||
account: Id
|
||||
account: Id,
|
||||
chat: Id
|
||||
) {
|
||||
chatContainer
|
||||
.watch(params.ctx)
|
||||
.watch(chat = chat)
|
||||
.onEach { Timber.d("Got new update: $it") }
|
||||
.collect {
|
||||
messages.value = it.map { msg ->
|
||||
val member = members.get().let { type ->
|
||||
when(type) {
|
||||
when (type) {
|
||||
is Store.Data -> type.members.find { member ->
|
||||
member.identity == msg.creator
|
||||
}
|
||||
|
||||
is Store.Empty -> null
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +125,7 @@ class DiscussionViewModel(
|
|||
author = member?.name ?: msg.creator.takeLast(5),
|
||||
isUserAuthor = msg.creator == account,
|
||||
isEdited = msg.modifiedAt > msg.createdAt,
|
||||
reactions = msg.reactions.map{ (emoji, ids) ->
|
||||
reactions = msg.reactions.map { (emoji, ids) ->
|
||||
DiscussionView.Message.Reaction(
|
||||
emoji = emoji,
|
||||
count = ids.size,
|
||||
|
@ -121,12 +148,12 @@ class DiscussionViewModel(
|
|||
fun onMessageSent(msg: String) {
|
||||
Timber.d("DROID-2635 OnMessageSent: $msg")
|
||||
viewModelScope.launch {
|
||||
when(val mode = chatBoxMode.value) {
|
||||
when (val mode = chatBoxMode.value) {
|
||||
is ChatBoxMode.Default -> {
|
||||
// TODO consider moving this use-case inside chat container
|
||||
addChatMessage.async(
|
||||
params = Command.ChatCommand.AddMessage(
|
||||
chat = params.ctx,
|
||||
chat = chat,
|
||||
message = Chat.Message.new(
|
||||
text = msg,
|
||||
attachments = attachments.value.map { a ->
|
||||
|
@ -146,10 +173,11 @@ class DiscussionViewModel(
|
|||
Timber.e(it, "Error while adding message")
|
||||
}
|
||||
}
|
||||
|
||||
is ChatBoxMode.EditMessage -> {
|
||||
editChatMessage.async(
|
||||
params = Command.ChatCommand.EditMessage(
|
||||
chat = params.ctx,
|
||||
chat = chat,
|
||||
message = Chat.Message.updated(
|
||||
id = mode.msg,
|
||||
text = msg
|
||||
|
@ -181,7 +209,7 @@ class DiscussionViewModel(
|
|||
name.value = input
|
||||
setObjectDetails.async(
|
||||
params = SetObjectDetails.Params(
|
||||
ctx = params.ctx,
|
||||
ctx = chat,
|
||||
details = mapOf(
|
||||
Relations.NAME to input
|
||||
)
|
||||
|
@ -209,7 +237,7 @@ class DiscussionViewModel(
|
|||
if (message != null) {
|
||||
toggleChatMessageReaction.async(
|
||||
Command.ChatCommand.ToggleMessageReaction(
|
||||
chat = params.ctx,
|
||||
chat = chat,
|
||||
msg = msg,
|
||||
emoji = reaction
|
||||
)
|
||||
|
@ -227,7 +255,7 @@ class DiscussionViewModel(
|
|||
viewModelScope.launch {
|
||||
deleteChatMessage.async(
|
||||
Command.ChatCommand.DeleteMessage(
|
||||
chat = params.ctx,
|
||||
chat = chat,
|
||||
msg = msg.id
|
||||
)
|
||||
).onFailure {
|
||||
|
@ -242,7 +270,7 @@ class DiscussionViewModel(
|
|||
navigation.emit(
|
||||
OpenObjectNavigation.OpenEditor(
|
||||
target = attachment.target,
|
||||
space = params.space.id
|
||||
space = vmParams.space.id
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -255,8 +283,8 @@ class DiscussionViewModel(
|
|||
}
|
||||
|
||||
sealed class UXCommand {
|
||||
data object JumpToBottom: UXCommand()
|
||||
data class SetChatBoxInput(val input: String): UXCommand()
|
||||
data object JumpToBottom : UXCommand()
|
||||
data class SetChatBoxInput(val input: String) : UXCommand()
|
||||
}
|
||||
|
||||
sealed class ChatBoxMode {
|
||||
|
@ -264,6 +292,20 @@ class DiscussionViewModel(
|
|||
data class EditMessage(val msg: Id) : ChatBoxMode()
|
||||
}
|
||||
|
||||
sealed class Params {
|
||||
|
||||
abstract val space: Space
|
||||
|
||||
data class Default(
|
||||
val ctx: Id,
|
||||
override val space: Space
|
||||
) : Params()
|
||||
|
||||
data class SpaceLevelChat(
|
||||
override val space: Space
|
||||
) : Params()
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Delay before jump-to-bottom after adding new message to the chat.
|
||||
|
|
|
@ -10,13 +10,14 @@ import com.anytypeio.anytype.domain.chats.EditChatMessage
|
|||
import com.anytypeio.anytype.domain.chats.ToggleChatMessageReaction
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.`object`.OpenObject
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
class DiscussionViewModelFactory @Inject constructor(
|
||||
private val params: BaseViewModel.DefaultParams,
|
||||
private val params: DiscussionViewModel.Params,
|
||||
private val setObjectDetails: SetObjectDetails,
|
||||
private val openObject: OpenObject,
|
||||
private val chatContainer: ChatContainer,
|
||||
|
@ -26,11 +27,12 @@ class DiscussionViewModelFactory @Inject constructor(
|
|||
private val toggleChatMessageReaction: ToggleChatMessageReaction,
|
||||
private val members: ActiveSpaceMemberSubscriptionContainer,
|
||||
private val getAccount: GetAccount,
|
||||
private val urlBuilder: UrlBuilder
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val spaceViews: SpaceViewSubscriptionContainer
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T = DiscussionViewModel(
|
||||
params = params,
|
||||
vmParams = params,
|
||||
setObjectDetails = setObjectDetails,
|
||||
openObject = openObject,
|
||||
chatContainer = chatContainer,
|
||||
|
@ -40,6 +42,7 @@ class DiscussionViewModelFactory @Inject constructor(
|
|||
getAccount = getAccount,
|
||||
deleteChatMessage = deleteChatMessage,
|
||||
urlBuilder = urlBuilder,
|
||||
editChatMessage = editChatMessage
|
||||
editChatMessage = editChatMessage,
|
||||
spaceViews = spaceViews
|
||||
) as T
|
||||
}
|
|
@ -80,7 +80,8 @@ fun DiscussionScreenPreview() {
|
|||
onDeleteMessage = {},
|
||||
onAttachmentClicked = {},
|
||||
onEditMessage = {},
|
||||
onExitEditMessageMode = {}
|
||||
onExitEditMessageMode = {},
|
||||
isSpaceLevelChat = true
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
|||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
@ -122,6 +121,7 @@ import kotlinx.coroutines.launch
|
|||
|
||||
@Composable
|
||||
fun DiscussionScreenWrapper(
|
||||
isSpaceLevelChat: Boolean = false,
|
||||
vm: DiscussionViewModel,
|
||||
// TODO move to view model
|
||||
onAttachClicked: () -> Unit
|
||||
|
@ -136,13 +136,20 @@ fun DiscussionScreenWrapper(
|
|||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
color = colorResource(id = R.color.background_primary)
|
||||
.then(
|
||||
if (!isSpaceLevelChat) {
|
||||
Modifier.background(
|
||||
color = colorResource(id = R.color.background_primary)
|
||||
)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
)
|
||||
) {
|
||||
val clipboard = LocalClipboardManager.current
|
||||
val lazyListState = rememberLazyListState()
|
||||
DiscussionScreen(
|
||||
isSpaceLevelChat = isSpaceLevelChat,
|
||||
title = vm.name.collectAsState().value,
|
||||
messages = vm.messages.collectAsState().value,
|
||||
attachments = vm.attachments.collectAsState().value,
|
||||
|
@ -185,6 +192,7 @@ fun DiscussionScreenWrapper(
|
|||
*/
|
||||
@Composable
|
||||
fun DiscussionScreen(
|
||||
isSpaceLevelChat: Boolean,
|
||||
isInEditMessageMode: Boolean = false,
|
||||
lazyListState: LazyListState,
|
||||
title: String?,
|
||||
|
@ -221,14 +229,22 @@ fun DiscussionScreen(
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.windowInsetsPadding(WindowInsets.systemBars)
|
||||
.then(
|
||||
if (isSpaceLevelChat)
|
||||
Modifier
|
||||
else
|
||||
Modifier.windowInsetsPadding(WindowInsets.systemBars)
|
||||
)
|
||||
) {
|
||||
TopDiscussionToolbar(
|
||||
title = title,
|
||||
isHeaderVisible = isHeaderVisible
|
||||
)
|
||||
if (!isSpaceLevelChat) {
|
||||
TopDiscussionToolbar(
|
||||
title = title,
|
||||
isHeaderVisible = isHeaderVisible
|
||||
)
|
||||
}
|
||||
Box(modifier = Modifier.weight(1.0f)) {
|
||||
Messages(
|
||||
isSpaceLevelChat = isSpaceLevelChat,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
messages = messages,
|
||||
scrollState = lazyListState,
|
||||
|
@ -408,12 +424,6 @@ private fun ChatBox(
|
|||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.then(
|
||||
if (isTitleFocused)
|
||||
Modifier
|
||||
else
|
||||
Modifier.imePadding()
|
||||
)
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = 56.dp)
|
||||
) {
|
||||
|
@ -598,6 +608,7 @@ private fun DefaultHintDecorationBox(
|
|||
|
||||
@Composable
|
||||
fun Messages(
|
||||
isSpaceLevelChat: Boolean = true,
|
||||
title: String?,
|
||||
onTitleChanged: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
@ -704,21 +715,23 @@ fun Messages(
|
|||
}
|
||||
}
|
||||
}
|
||||
item(key = HEADER_KEY) {
|
||||
Column {
|
||||
DiscussionTitle(
|
||||
title = title,
|
||||
onTitleChanged = onTitleChanged,
|
||||
onFocusChanged = onTitleFocusChanged
|
||||
)
|
||||
Text(
|
||||
style = Relations2,
|
||||
text = stringResource(R.string.chat),
|
||||
color = colorResource(id = R.color.text_secondary),
|
||||
modifier = Modifier.padding(
|
||||
start = 20.dp
|
||||
if (!isSpaceLevelChat) {
|
||||
item(key = HEADER_KEY) {
|
||||
Column {
|
||||
DiscussionTitle(
|
||||
title = title,
|
||||
onTitleChanged = onTitleChanged,
|
||||
onFocusChanged = onTitleFocusChanged
|
||||
)
|
||||
)
|
||||
Text(
|
||||
style = Relations2,
|
||||
text = stringResource(R.string.chat),
|
||||
color = colorResource(id = R.color.text_secondary),
|
||||
modifier = Modifier.padding(
|
||||
start = 20.dp
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -763,6 +776,9 @@ private fun ChatUserAvatar(
|
|||
}
|
||||
}
|
||||
|
||||
val defaultBubbleColor = Color(0x99FFFFFF)
|
||||
val userMessageBubbleColor = Color(0x66000000)
|
||||
|
||||
@Composable
|
||||
fun Bubble(
|
||||
modifier: Modifier = Modifier,
|
||||
|
@ -785,9 +801,9 @@ fun Bubble(
|
|||
.fillMaxWidth()
|
||||
.background(
|
||||
color = if (isUserAuthor)
|
||||
colorResource(id = R.color.palette_very_light_lime)
|
||||
userMessageBubbleColor
|
||||
else
|
||||
colorResource(id = R.color.palette_very_light_grey),
|
||||
defaultBubbleColor,
|
||||
shape = RoundedCornerShape(24.dp)
|
||||
)
|
||||
.clip(RoundedCornerShape(24.dp))
|
||||
|
@ -805,7 +821,10 @@ fun Bubble(
|
|||
Text(
|
||||
text = name,
|
||||
style = PreviewTitle2Medium,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
color = if (isUserAuthor)
|
||||
colorResource(id = R.color.text_white)
|
||||
else
|
||||
colorResource(id = R.color.text_primary),
|
||||
maxLines = 1,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
|
@ -814,7 +833,10 @@ fun Bubble(
|
|||
TIME_H24
|
||||
),
|
||||
style = Caption1Regular,
|
||||
color = colorResource(id = R.color.text_secondary),
|
||||
color = if (isUserAuthor)
|
||||
colorResource(id = R.color.text_white)
|
||||
else
|
||||
colorResource(id = R.color.text_secondary),
|
||||
maxLines = 1
|
||||
)
|
||||
}
|
||||
|
@ -829,7 +851,12 @@ fun Bubble(
|
|||
text = buildAnnotatedString {
|
||||
append(msg)
|
||||
withStyle(
|
||||
style = SpanStyle(color = colorResource(id = R.color.text_secondary))
|
||||
style = SpanStyle(
|
||||
color = if (isUserAuthor)
|
||||
colorResource(id = R.color.text_white)
|
||||
else
|
||||
colorResource(id = R.color.text_primary),
|
||||
)
|
||||
) {
|
||||
append(
|
||||
" (${stringResource(R.string.chats_message_edited)})"
|
||||
|
@ -849,7 +876,10 @@ fun Bubble(
|
|||
),
|
||||
text = msg,
|
||||
style = BodyRegular,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
color = if (isUserAuthor)
|
||||
colorResource(id = R.color.text_white)
|
||||
else
|
||||
colorResource(id = R.color.text_primary),
|
||||
)
|
||||
}
|
||||
attachments.forEach { attachment ->
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceAccessType
|
||||
import com.anytypeio.anytype.core_models.primitives.Space
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_models.restrictions.SpaceStatus
|
||||
import com.anytypeio.anytype.core_utils.ext.allUniqueBy
|
||||
|
@ -141,14 +142,15 @@ class SelectSpaceViewModel(
|
|||
Timber.d("Setting space: $view")
|
||||
if (!view.isSelected) {
|
||||
analytics.sendEvent(eventName = EventsDictionary.switchSpace)
|
||||
spaceManager.set(view.space).fold(
|
||||
val space = SpaceId(view.space)
|
||||
spaceManager.set(space.id).fold(
|
||||
onSuccess = {
|
||||
saveCurrentSpace.async(SaveCurrentSpace.Params(SpaceId(view.space))).fold(
|
||||
saveCurrentSpace.async(SaveCurrentSpace.Params(space)).fold(
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while saving current space in user settings")
|
||||
},
|
||||
onSuccess = {
|
||||
commands.emit(Command.SwitchToNewSpace)
|
||||
commands.emit(Command.SwitchToNewSpace(space))
|
||||
}
|
||||
)
|
||||
},
|
||||
|
@ -239,5 +241,5 @@ sealed class SelectSpaceView {
|
|||
sealed class Command {
|
||||
data object CreateSpace : Command()
|
||||
data object Dismiss : Command()
|
||||
data object SwitchToNewSpace: Command()
|
||||
data class SwitchToNewSpace(val space: Space): Command()
|
||||
}
|
|
@ -274,7 +274,10 @@ class SplashViewModel(
|
|||
private suspend fun proceedWithVaultNavigation(deeplink: String? = null) {
|
||||
val space = getLastOpenedSpace.async(Unit).getOrNull()
|
||||
if (space != null) {
|
||||
commands.emit(Command.NavigateToWidgets(deeplink))
|
||||
commands.emit(Command.NavigateToWidgets(
|
||||
space = space.id,
|
||||
deeplink = deeplink
|
||||
))
|
||||
} else {
|
||||
commands.emit(Command.NavigateToVault(deeplink))
|
||||
}
|
||||
|
@ -305,7 +308,7 @@ class SplashViewModel(
|
|||
}
|
||||
|
||||
sealed class Command {
|
||||
data class NavigateToWidgets(val deeplink: String? = null) : Command()
|
||||
data class NavigateToWidgets(val space: Id, val deeplink: String? = null) : Command()
|
||||
data class NavigateToVault(val deeplink: String? = null) : Command()
|
||||
data object NavigateToAuthStart : Command()
|
||||
data object NavigateToMigration: Command()
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.anytypeio.anytype.analytics.props.Props
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Wallpaper
|
||||
import com.anytypeio.anytype.core_models.primitives.Space
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_models.restrictions.SpaceStatus
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
|
@ -240,7 +241,11 @@ class VaultViewModel(
|
|||
Timber.e(it, "Error while saving current space on vault screen")
|
||||
},
|
||||
onSuccess = {
|
||||
commands.emit(Command.EnterSpaceHomeScreen)
|
||||
commands.emit(
|
||||
Command.EnterSpaceHomeScreen(
|
||||
space = Space(targetSpace)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -321,7 +326,7 @@ class VaultViewModel(
|
|||
)
|
||||
|
||||
sealed class Command {
|
||||
data object EnterSpaceHomeScreen: Command()
|
||||
data class EnterSpaceHomeScreen(val space: Space): Command()
|
||||
data object CreateNewSpace: Command()
|
||||
data object OpenProfileSettings: Command()
|
||||
data object ShowIntroduceVault : Command()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue