mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3662 Chats | Enhancement | Introduce system widget "Chat" + navigation changes (#2420)
This commit is contained in:
parent
d7946bd54d
commit
5bddcd640c
21 changed files with 175 additions and 82 deletions
|
@ -1666,6 +1666,12 @@ fun CoroutineScope.sendChangeWidgetSourceEvent(
|
|||
BundledWidgetSourceView.AllObjects -> {
|
||||
put(WidgetAnalytics.TYPE, WidgetAnalytics.WIDGET_SOURCE_ALL_OBJECTS)
|
||||
}
|
||||
BundledWidgetSourceView.AllObjects -> {
|
||||
put(WidgetAnalytics.TYPE, WidgetAnalytics.WIDGET_SOURCE_CHAT)
|
||||
}
|
||||
BundledWidgetSourceView.Chat -> {
|
||||
put(WidgetAnalytics.TYPE, WidgetAnalytics.WIDGET_SOURCE_CHAT)
|
||||
}
|
||||
}
|
||||
if (isForNewWidget)
|
||||
put(WidgetAnalytics.ROUTE, WidgetAnalytics.ROUTE_ADD_WIDGET)
|
||||
|
@ -1769,6 +1775,9 @@ fun CoroutineScope.sendDeleteWidgetEvent(
|
|||
Widget.Source.Bundled.AllObjects -> {
|
||||
put(WidgetAnalytics.TYPE, WidgetAnalytics.WIDGET_SOURCE_ALL_OBJECTS)
|
||||
}
|
||||
Widget.Source.Bundled.Chat -> {
|
||||
put(WidgetAnalytics.TYPE, WidgetAnalytics.WIDGET_SOURCE_CHAT)
|
||||
}
|
||||
}
|
||||
if (isInEditMode)
|
||||
put(WidgetAnalytics.CONTEXT, WidgetAnalytics.CONTEXT_EDITOR)
|
||||
|
@ -1814,6 +1823,9 @@ fun CoroutineScope.sendClickWidgetTitleEvent(
|
|||
Widget.Source.Bundled.AllObjects -> {
|
||||
put(WidgetAnalytics.TAB, WidgetAnalytics.WIDGET_SOURCE_ALL_OBJECTS)
|
||||
}
|
||||
Widget.Source.Bundled.Chat -> {
|
||||
put(WidgetAnalytics.TAB, WidgetAnalytics.WIDGET_SOURCE_CHAT)
|
||||
}
|
||||
}
|
||||
|
||||
isAutoCreated?.let {
|
||||
|
@ -1902,6 +1914,9 @@ fun CoroutineScope.sendReorderWidgetEvent(
|
|||
Widget.Source.Bundled.AllObjects -> {
|
||||
put(WidgetAnalytics.TYPE, WidgetAnalytics.WIDGET_SOURCE_ALL_OBJECTS)
|
||||
}
|
||||
Widget.Source.Bundled.Chat -> {
|
||||
put(WidgetAnalytics.TYPE, WidgetAnalytics.WIDGET_SOURCE_CHAT)
|
||||
}
|
||||
}
|
||||
|
||||
isAutoCreated?.let {
|
||||
|
|
|
@ -136,6 +136,7 @@ import com.anytypeio.anytype.presentation.widgets.WidgetId
|
|||
import com.anytypeio.anytype.presentation.widgets.WidgetSessionStateHolder
|
||||
import com.anytypeio.anytype.presentation.widgets.WidgetView
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.Subscription
|
||||
import com.anytypeio.anytype.presentation.widgets.forceChatPosition
|
||||
import com.anytypeio.anytype.presentation.widgets.hasValidLayout
|
||||
import com.anytypeio.anytype.presentation.widgets.parseActiveViews
|
||||
import com.anytypeio.anytype.presentation.widgets.parseWidgets
|
||||
|
@ -503,7 +504,8 @@ class HomeScreenViewModel(
|
|||
viewModelScope.launch {
|
||||
widgets.filterNotNull().map { widgets ->
|
||||
val currentlyDisplayedViews = views.value
|
||||
widgets.filter { widget -> widget.hasValidLayout() }.map { widget ->
|
||||
|
||||
widgets.forceChatPosition().filter { widget -> widget.hasValidLayout() }.map { widget ->
|
||||
when (widget) {
|
||||
is Widget.Link -> LinkWidgetContainer(
|
||||
widget = widget,
|
||||
|
@ -738,6 +740,7 @@ class HomeScreenViewModel(
|
|||
if (
|
||||
dispatch.source == BundledWidgetSourceView.AllObjects.id
|
||||
|| dispatch.source == BundledWidgetSourceView.Bin.id
|
||||
|| dispatch.source == BundledWidgetSourceView.Chat.id
|
||||
) {
|
||||
// Applying link layout automatically to all-objects widget
|
||||
proceedWithCreatingWidget(
|
||||
|
@ -1105,6 +1108,26 @@ class HomeScreenViewModel(
|
|||
)
|
||||
}
|
||||
}
|
||||
is Widget.Source.Bundled.Chat -> {
|
||||
viewModelScope.launch {
|
||||
if (mode.value == InteractionMode.Edit) {
|
||||
return@launch
|
||||
}
|
||||
val space = spaceManager.get()
|
||||
val view = spaceViewSubscriptionContainer.get(SpaceId(space))
|
||||
val chat = view?.chatId
|
||||
if (chat != null) {
|
||||
navigation(
|
||||
Navigation.OpenChat(
|
||||
ctx = chat,
|
||||
space = space
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Timber.w("Failed to open chat from widget: chat not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2487,41 +2510,46 @@ class HomeScreenViewModel(
|
|||
viewModelScope.launch {
|
||||
val source = view.source
|
||||
if (source is Widget.Source.Default) {
|
||||
if (source.obj.layout == ObjectType.Layout.OBJECT_TYPE) {
|
||||
val wrapper = ObjectWrapper.Type(source.obj.map)
|
||||
val space = SpaceId(spaceManager.get())
|
||||
val startTime = System.currentTimeMillis()
|
||||
createObject.async(
|
||||
params = CreateObject.Param(
|
||||
space = space,
|
||||
type = TypeKey(wrapper.uniqueKey),
|
||||
prefilled = mapOf(Relations.IS_FAVORITE to true)
|
||||
)
|
||||
).onSuccess { result ->
|
||||
sendAnalyticsObjectCreateEvent(
|
||||
objType = wrapper.uniqueKey,
|
||||
analytics = analytics,
|
||||
route = EventsDictionary.Routes.widget,
|
||||
startTime = startTime,
|
||||
view = null,
|
||||
spaceParams = provideParams(space.id)
|
||||
)
|
||||
proceedWithNavigation(result.obj.navigation())
|
||||
when (source.obj.layout) {
|
||||
ObjectType.Layout.OBJECT_TYPE -> {
|
||||
val wrapper = ObjectWrapper.Type(source.obj.map)
|
||||
val space = SpaceId(spaceManager.get())
|
||||
val startTime = System.currentTimeMillis()
|
||||
createObject.async(
|
||||
params = CreateObject.Param(
|
||||
space = space,
|
||||
type = TypeKey(wrapper.uniqueKey),
|
||||
prefilled = mapOf(Relations.IS_FAVORITE to true)
|
||||
)
|
||||
).onSuccess { result ->
|
||||
sendAnalyticsObjectCreateEvent(
|
||||
objType = wrapper.uniqueKey,
|
||||
analytics = analytics,
|
||||
route = EventsDictionary.Routes.widget,
|
||||
startTime = startTime,
|
||||
view = null,
|
||||
spaceParams = provideParams(space.id)
|
||||
)
|
||||
proceedWithNavigation(result.obj.navigation())
|
||||
}
|
||||
}
|
||||
ObjectType.Layout.COLLECTION -> {
|
||||
onCreateDataViewObject(
|
||||
widget = view.id,
|
||||
view = null,
|
||||
navigate = true
|
||||
)
|
||||
}
|
||||
ObjectType.Layout.SET -> {
|
||||
onCreateDataViewObject(
|
||||
widget = view.id,
|
||||
view = null,
|
||||
navigate = true
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Timber.w("Unexpected source layout: ${source.obj.layout}")
|
||||
}
|
||||
} else if (source.obj.layout == ObjectType.Layout.COLLECTION) {
|
||||
onCreateDataViewObject(
|
||||
widget = view.id,
|
||||
view = null,
|
||||
navigate = true
|
||||
)
|
||||
} else if (source.obj.layout == ObjectType.Layout.SET) {
|
||||
onCreateDataViewObject(
|
||||
widget = view.id,
|
||||
view = null,
|
||||
navigate = true
|
||||
)
|
||||
} else {
|
||||
Timber.w("Unexpected source layout: ${source.obj.layout}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ interface AppNavigation {
|
|||
)
|
||||
fun openChat(target: Id, space: Id)
|
||||
fun openDocument(target: Id, space: Id)
|
||||
fun openDiscussion(target: Id, space: Id)
|
||||
fun openModalTemplateSelect(
|
||||
template: Id,
|
||||
templateTypeId: Id,
|
||||
|
@ -98,7 +97,7 @@ interface AppNavigation {
|
|||
val space: Id
|
||||
) : Command()
|
||||
|
||||
object OpenSettings : Command()
|
||||
data object OpenSettings : Command()
|
||||
|
||||
data class OpenShareScreen(
|
||||
val space: SpaceId
|
||||
|
@ -132,7 +131,7 @@ interface AppNavigation {
|
|||
|
||||
data class LaunchObjectSet(val target: Id, val space: Id) : Command()
|
||||
|
||||
object OpenUpdateAppScreen : Command()
|
||||
data object OpenUpdateAppScreen : Command()
|
||||
|
||||
data class DeletedAccountScreen(val deadline: Long) : Command()
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.anytypeio.anytype.core_models.ObjectTypeIds.COLLECTION
|
|||
import com.anytypeio.anytype.core_models.SupportedLayouts
|
||||
import com.anytypeio.anytype.core_models.exceptions.AccountMigrationNeededException
|
||||
import com.anytypeio.anytype.core_models.exceptions.NeedToUpdateApplicationException
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceType
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_models.primitives.TypeKey
|
||||
import com.anytypeio.anytype.core_models.restrictions.SpaceStatus
|
||||
|
@ -257,7 +258,7 @@ class SplashViewModel(
|
|||
Command.NavigateToObjectSet(
|
||||
id = target,
|
||||
space = spaceId,
|
||||
chat = view.chatId
|
||||
chat = if (view.spaceType == SpaceType.CHAT) view.chatId else null
|
||||
)
|
||||
)
|
||||
} else {
|
||||
|
@ -265,7 +266,7 @@ class SplashViewModel(
|
|||
Command.NavigateToObject(
|
||||
id = target,
|
||||
space = spaceId,
|
||||
chat = view.chatId
|
||||
chat = if (view.spaceType == SpaceType.CHAT) view.chatId else null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -317,7 +318,7 @@ class SplashViewModel(
|
|||
Command.NavigateToObjectSet(
|
||||
id = id,
|
||||
space = space,
|
||||
chat = view.chatId
|
||||
chat = if (view.spaceType == SpaceType.CHAT) view.chatId else null
|
||||
)
|
||||
)
|
||||
ObjectType.Layout.DATE -> {
|
||||
|
@ -325,7 +326,7 @@ class SplashViewModel(
|
|||
Command.NavigateToDateObject(
|
||||
id = id,
|
||||
space = space,
|
||||
chat = view.chatId
|
||||
chat = if (view.spaceType == SpaceType.CHAT) view.chatId else null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -334,7 +335,7 @@ class SplashViewModel(
|
|||
Command.NavigateToObjectType(
|
||||
id = id,
|
||||
space = space,
|
||||
chat = view.chatId
|
||||
chat = if (view.spaceType == SpaceType.CHAT) view.chatId else null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -343,7 +344,7 @@ class SplashViewModel(
|
|||
Command.NavigateToObject(
|
||||
id = id,
|
||||
space = space,
|
||||
chat = view.chatId
|
||||
chat = if (view.spaceType == SpaceType.CHAT) view.chatId else null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -398,7 +399,7 @@ class SplashViewModel(
|
|||
deeplink = deeplink
|
||||
)
|
||||
)
|
||||
} else {
|
||||
} else if (view.spaceType == SpaceType.CHAT) {
|
||||
commands.emit(
|
||||
Command.NavigateToSpaceLevelChat(
|
||||
space = space.id,
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.anytypeio.anytype.core_models.Event
|
|||
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.multiplayer.SpaceType
|
||||
import com.anytypeio.anytype.core_models.primitives.Space
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
|
@ -147,7 +148,8 @@ class VaultViewModel(
|
|||
onSuccess = {
|
||||
proceedWithSavingCurrentSpace(
|
||||
targetSpace = targetSpace,
|
||||
chat = view.space.chatId?.ifEmpty { null }
|
||||
chat = view.space.chatId?.ifEmpty { null },
|
||||
spaceType = view.space.spaceType
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -252,7 +254,8 @@ class VaultViewModel(
|
|||
|
||||
private suspend fun proceedWithSavingCurrentSpace(
|
||||
targetSpace: String,
|
||||
chat: Id?
|
||||
chat: Id?,
|
||||
spaceType: SpaceType?
|
||||
) {
|
||||
saveCurrentSpace.async(
|
||||
SaveCurrentSpace.Params(SpaceId(targetSpace))
|
||||
|
@ -261,7 +264,7 @@ class VaultViewModel(
|
|||
Timber.e(it, "Error while saving current space on vault screen")
|
||||
},
|
||||
onSuccess = {
|
||||
if (chat != null && ChatConfig.isChatAllowed(space = targetSpace)) {
|
||||
if (spaceType == SpaceType.CHAT && chat != null && ChatConfig.isChatAllowed(space = targetSpace)) {
|
||||
commands.emit(
|
||||
Command.EnterSpaceLevelChat(
|
||||
space = Space(targetSpace),
|
||||
|
|
|
@ -130,6 +130,9 @@ class SelectWidgetSourceViewModel(
|
|||
if (contains(BundledWidgetSourceIds.ALL_OBJECTS)) {
|
||||
add(BundledWidgetSourceView.AllObjects)
|
||||
}
|
||||
if (contains(BundledWidgetSourceIds.CHAT)) {
|
||||
add(BundledWidgetSourceView.Chat)
|
||||
}
|
||||
if (contains(BundledWidgetSourceIds.RECENT)) {
|
||||
add(BundledWidgetSourceView.Recent)
|
||||
}
|
||||
|
@ -270,6 +273,7 @@ class SelectWidgetSourceViewModel(
|
|||
if (
|
||||
view is BundledWidgetSourceView.AllObjects
|
||||
|| view is BundledWidgetSourceView.Bin
|
||||
|| view is BundledWidgetSourceView.Chat
|
||||
) {
|
||||
isDismissed.value = true
|
||||
}
|
||||
|
|
|
@ -109,10 +109,24 @@ sealed class Widget {
|
|||
override val id: Id = BundledWidgetSourceIds.ALL_OBJECTS
|
||||
override val type: Id? = null
|
||||
}
|
||||
|
||||
data object Chat : Bundled() {
|
||||
override val id: Id = BundledWidgetSourceIds.CHAT
|
||||
override val type: Id? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun List<Widget>.forceChatPosition(): List<Widget> {
|
||||
// Partition the list into chat widgets and the rest
|
||||
val (chatWidgets, otherWidgets) = partition { widget ->
|
||||
widget.source is Widget.Source.Bundled.Chat
|
||||
}
|
||||
// Place chat widgets first, followed by the others
|
||||
return chatWidgets + otherWidgets
|
||||
}
|
||||
|
||||
fun Widget.hasValidLayout(): Boolean = when (val widgetSource = source) {
|
||||
is Widget.Source.Default -> isSupportedForWidgets(widgetSource.obj.layout)
|
||||
is Widget.Source.Bundled -> true
|
||||
|
@ -246,6 +260,7 @@ fun Id.bundled() : Widget.Source.Bundled = when (this) {
|
|||
BundledWidgetSourceIds.FAVORITE -> Widget.Source.Bundled.Favorites
|
||||
BundledWidgetSourceIds.BIN -> Widget.Source.Bundled.Bin
|
||||
BundledWidgetSourceIds.ALL_OBJECTS -> Widget.Source.Bundled.AllObjects
|
||||
BundledWidgetSourceIds.CHAT -> Widget.Source.Bundled.Chat
|
||||
else -> throw IllegalStateException("Widget bundled id can't be $this")
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ sealed class WidgetView {
|
|||
val canCreateObjectOfType : Boolean get() {
|
||||
return when(source) {
|
||||
Widget.Source.Bundled.AllObjects -> false
|
||||
Widget.Source.Bundled.Chat -> false
|
||||
Widget.Source.Bundled.Bin -> false
|
||||
Widget.Source.Bundled.Favorites -> true
|
||||
Widget.Source.Bundled.Recent -> false
|
||||
|
|
|
@ -29,6 +29,10 @@ sealed class BundledWidgetSourceView : DefaultSearchItem {
|
|||
data object AllObjects : BundledWidgetSourceView() {
|
||||
override val id: Id get() = BundledWidgetSourceIds.ALL_OBJECTS
|
||||
}
|
||||
|
||||
data object Chat : BundledWidgetSourceView() {
|
||||
override val id: Id get() = BundledWidgetSourceIds.CHAT
|
||||
}
|
||||
}
|
||||
|
||||
data class SuggestWidgetObjectType(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue