diff --git a/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt
index 1ec22c6450..ef3c7b3c83 100644
--- a/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt
+++ b/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt
@@ -5,7 +5,9 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.os.bundleOf
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.anytypeio.anytype.R
@@ -25,6 +27,8 @@ import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetFragment
import com.anytypeio.anytype.core_utils.ui.proceed
import com.anytypeio.anytype.core_utils.ui.showActionableSnackBar
import com.anytypeio.anytype.databinding.FragmentObjectMenuBinding
+import com.anytypeio.anytype.feature_object_type.ui.conflict.ConflictScreen
+import com.anytypeio.anytype.feature_object_type.ui.conflict.ConflictScreenPreview
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.menu.ObjectMenuOptionsProvider
import com.anytypeio.anytype.presentation.objects.menu.ObjectMenuViewModelBase
@@ -78,6 +82,16 @@ abstract class ObjectMenuBaseFragment :
)
)
}
+ binding.objectLayoutConflictScreen.apply {
+ setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
+ setContent {
+ ConflictScreen(
+ showScreen = vm.showLayoutConflictScreen.collectAsStateWithLifecycle().value,
+ onResetClick = { },
+ onDismiss = { vm.onHideConflictScreen() }
+ )
+ }
+ }
}
override fun onStart() {
@@ -88,6 +102,7 @@ abstract class ObjectMenuBaseFragment :
click(binding.optionRelations) { vm.onRelationsClicked() }
click(binding.optionCover) { vm.onCoverClicked(ctx = ctx, space = space) }
click(binding.debugGoroutines) { vm.onDiagnosticsGoroutinesClicked(ctx = ctx) }
+ click(binding.objectLayoutConflict) { vm.onShowConflictScreen(objectId = ctx, space = space) }
proceed(vm.actions) { actionAdapter.submitList(it) }
proceed(vm.toasts) { toast(it) }
@@ -162,11 +177,15 @@ abstract class ObjectMenuBaseFragment :
snackbar.anchorView = binding.anchor
snackbar.show()
}
+
is ObjectMenuViewModelBase.Command.ShareDeeplinkToObject -> {
val intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, command.link)
- putExtra(Intent.EXTRA_TITLE, getString(R.string.multiplayer_deeplink_to_your_object))
+ putExtra(
+ Intent.EXTRA_TITLE,
+ getString(R.string.multiplayer_deeplink_to_your_object)
+ )
type = "text/plain"
}
startActivity(Intent.createChooser(intent, null))
diff --git a/app/src/main/res/layout/fragment_object_menu.xml b/app/src/main/res/layout/fragment_object_menu.xml
index c41ba63113..658669995e 100644
--- a/app/src/main/res/layout/fragment_object_menu.xml
+++ b/app/src/main/res/layout/fragment_object_menu.xml
@@ -1,192 +1,216 @@
-
+ android:layout_height="match_parent">
-
-
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
-
+
+
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ app:layout_constraintBottom_toTopOf="@id/rvContainer"
+ app:layout_constraintTop_toTopOf="parent">
-
-
-
-
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+ android:layout_height="108dp"
+ android:layout_marginTop="12dp"
+ android:layout_weight="0">
-
+
-
+
+
+
+
+
+
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal" />
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/ObjectMenuItemWidget.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/ObjectMenuItemWidget.kt
index 63d7f4a2c4..d2748b9ecc 100644
--- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/ObjectMenuItemWidget.kt
+++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/ObjectMenuItemWidget.kt
@@ -6,6 +6,8 @@ import android.view.LayoutInflater
import android.widget.LinearLayout
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.WidgetObjectMenuItemBinding
+import com.anytypeio.anytype.core_utils.ext.invisible
+import com.anytypeio.anytype.core_utils.ext.visible
class ObjectMenuItemWidget @JvmOverloads constructor(
context: Context,
@@ -26,6 +28,12 @@ class ObjectMenuItemWidget @JvmOverloads constructor(
val attrs = context.obtainStyledAttributes(set, R.styleable.ObjectMenuItemWidget, 0, 0)
tvTitle.text = attrs.getString(R.styleable.ObjectMenuItemWidget_title)
ivIcon.setImageResource(attrs.getResourceId(R.styleable.ObjectMenuItemWidget_icon, -1))
+ val showArrow = attrs.getBoolean(R.styleable.ObjectMenuItemWidget_showArrow, true)
+ if (showArrow) {
+ ivArrow.visible()
+ } else {
+ ivArrow.invisible()
+ }
attrs.recycle()
}
}
\ No newline at end of file
diff --git a/core-ui/src/main/res/drawable/ic_attention_24.xml b/core-ui/src/main/res/drawable/ic_attention_24.xml
new file mode 100644
index 0000000000..fd6d520549
--- /dev/null
+++ b/core-ui/src/main/res/drawable/ic_attention_24.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/core-ui/src/main/res/values/attrs.xml b/core-ui/src/main/res/values/attrs.xml
index 5762924d05..694a221007 100644
--- a/core-ui/src/main/res/values/attrs.xml
+++ b/core-ui/src/main/res/values/attrs.xml
@@ -49,6 +49,7 @@
+
diff --git a/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/ui/conflict/ConflictScreen.kt b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/ui/conflict/ConflictScreen.kt
new file mode 100644
index 0000000000..a42117aaa4
--- /dev/null
+++ b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/ui/conflict/ConflictScreen.kt
@@ -0,0 +1,113 @@
+package com.anytypeio.anytype.feature_object_type.ui.conflict
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.Text
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import com.anytypeio.anytype.core_ui.common.DefaultPreviews
+import com.anytypeio.anytype.core_ui.foundation.Dragger
+import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular
+import com.anytypeio.anytype.core_ui.views.ButtonPrimary
+import com.anytypeio.anytype.core_ui.views.ButtonSecondary
+import com.anytypeio.anytype.core_ui.views.ButtonSize
+import com.anytypeio.anytype.core_ui.views.HeadlineSubheading
+import com.anytypeio.anytype.feature_object_type.R
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun ConflictScreen(
+ modifier: Modifier = Modifier,
+ showScreen: Boolean,
+ onResetClick: () -> Unit,
+ onDismiss: () -> Unit,
+) {
+ val bottomSheetState = rememberModalBottomSheetState(
+ skipPartiallyExpanded = true
+ )
+
+ if (showScreen) {
+ ModalBottomSheet(
+ modifier = modifier,
+ dragHandle = {
+ Column {
+ Spacer(modifier = Modifier.height(6.dp))
+ Dragger()
+ Spacer(modifier = Modifier.height(6.dp))
+ }
+ },
+ scrimColor = colorResource(id = R.color.modal_screen_outside_background),
+ containerColor = colorResource(id = R.color.background_secondary),
+ shape = RoundedCornerShape(16.dp),
+ sheetState = bottomSheetState,
+ onDismissRequest = {
+ onDismiss()
+ }
+ ) {
+ Spacer(modifier = Modifier.height(20.dp))
+ Text(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 20.dp),
+ textAlign = TextAlign.Center,
+ style = HeadlineSubheading,
+ color = colorResource(id = R.color.text_primary),
+ text = stringResource(id = R.string.object_conflict_screen_title)
+ )
+ Spacer(modifier = Modifier.height(4.dp))
+ Text(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 20.dp),
+ textAlign = TextAlign.Center,
+ style = BodyCalloutRegular,
+ color = colorResource(id = R.color.text_primary),
+ text = stringResource(id = R.string.object_conflict_screen_description)
+ )
+ Spacer(modifier = Modifier.height(20.dp))
+ ButtonPrimary(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 20.dp),
+ text = stringResource(R.string.object_conflict_screen_action_button),
+ size = ButtonSize.LargeSecondary,
+ onClick = {
+ onResetClick()
+ }
+ )
+ Spacer(modifier = Modifier.height(8.dp))
+ ButtonSecondary(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 20.dp),
+ text = stringResource(R.string.cancel),
+ size = ButtonSize.LargeSecondary,
+ onClick = {
+ onDismiss()
+ }
+ )
+ Spacer(modifier = Modifier.height(10.dp))
+ }
+ }
+}
+
+@DefaultPreviews
+@Composable
+fun ConflictScreenPreview() {
+ ConflictScreen(
+ showScreen = true,
+ onResetClick = {},
+ onDismiss = {}
+ )
+}
\ No newline at end of file
diff --git a/localization/src/main/res/values/strings.xml b/localization/src/main/res/values/strings.xml
index 2e06a3c053..372d4382e1 100644
--- a/localization/src/main/res/values/strings.xml
+++ b/localization/src/main/res/values/strings.xml
@@ -2010,4 +2010,10 @@ Please provide specific details of your needs here.
Search..."
Space invite link copied!
+ Resolve layout conflict
+ This layout differs from the type\'s default. Reset to match?
+ Reset to default
+
+ Resolve layout conflict
+
\ No newline at end of file
diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt
index 91fdb6f3d5..08685fdd54 100644
--- a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt
+++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt
@@ -96,6 +96,8 @@ abstract class ObjectMenuViewModelBase(
abstract fun onDescriptionClicked(ctx: Id, space: Id)
abstract fun onRelationsClicked()
+ val showLayoutConflictScreen = MutableStateFlow(false)
+
fun onHistoryClicked(ctx: Id, space: Id) {
viewModelScope.launch {
commands.emit(Command.OpenHistoryScreen(ctx, space))
@@ -478,6 +480,18 @@ abstract class ObjectMenuViewModelBase(
}
}
+ fun onShowConflictScreen(objectId: Id, space: Id) {
+ viewModelScope.launch {
+ showLayoutConflictScreen.value = true
+ }
+ }
+
+ fun onHideConflictScreen() {
+ viewModelScope.launch {
+ showLayoutConflictScreen.value = false
+ }
+ }
+
sealed class Command {
data object OpenObjectIcons : Command()
data object OpenSetIcons : Command()