mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-498 App | Enhancement | Interface toast for structure change actions (#2648)
This commit is contained in:
parent
82fddb7b49
commit
1f1ab28617
25 changed files with 367 additions and 41 deletions
|
@ -0,0 +1,72 @@
|
|||
package com.anytypeio.anytype.core_utils.ui
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
||||
|
||||
fun View.showActionableSnackBar(from: String?, to: String?, icon: ObjectIcon, click: () -> Unit) {
|
||||
|
||||
val snackbar: Snackbar = Snackbar.make(this, "", Snackbar.LENGTH_SHORT)
|
||||
|
||||
snackbar.view.setBackgroundColor(Color.TRANSPARENT)
|
||||
val snackbarLayout: Snackbar.SnackbarLayout = snackbar.view as Snackbar.SnackbarLayout
|
||||
snackbarLayout.setPadding(0, 0, 0, 0)
|
||||
|
||||
val newView: View = LayoutInflater.from(context).inflate(R.layout.snackbar_actionable, null)
|
||||
newView.setOnClickListener { snackbar.dismiss() }
|
||||
|
||||
with(newView.findViewById<TextView>(R.id.snackbar_text)) {
|
||||
if (from.isNullOrEmpty()) {
|
||||
this.text =
|
||||
"${resources.getString(R.string.untitled)} ${resources.getString(R.string.snack_link_to)}"
|
||||
} else {
|
||||
this.text = "$from ${resources.getString(R.string.snack_link_to)}"
|
||||
}
|
||||
}
|
||||
|
||||
with(newView.findViewById<TextView>(R.id.snackbar_action)) {
|
||||
if (!to.isNullOrEmpty()) {
|
||||
this.text = to
|
||||
}
|
||||
setOnClickListener {
|
||||
click()
|
||||
snackbar.dismiss()
|
||||
}
|
||||
}
|
||||
if (icon != ObjectIcon.None) {
|
||||
with(newView.findViewById<ObjectIconWidget>(R.id.icon)) {
|
||||
isVisible = true
|
||||
setIcon(icon)
|
||||
}
|
||||
}
|
||||
|
||||
snackbarLayout.addView(newView, 0)
|
||||
|
||||
snackbar.show()
|
||||
}
|
||||
|
||||
fun View.showMessageSnackBar(text: String, anchor: View? = null) {
|
||||
|
||||
val snackbar: Snackbar = Snackbar.make(this, "", Snackbar.LENGTH_SHORT)
|
||||
|
||||
snackbar.view.setBackgroundColor(Color.TRANSPARENT)
|
||||
val snackbarLayout: Snackbar.SnackbarLayout = snackbar.view as Snackbar.SnackbarLayout
|
||||
snackbarLayout.setPadding(0, 0, 0, 0)
|
||||
|
||||
val newView: View = LayoutInflater.from(context).inflate(R.layout.snackbar_message, null)
|
||||
newView.setOnClickListener { snackbar.dismiss() }
|
||||
|
||||
newView.findViewById<TextView>(R.id.snackbar_text).text = text
|
||||
|
||||
snackbarLayout.addView(newView, 0)
|
||||
snackbar.anchorView = anchor
|
||||
|
||||
snackbar.show()
|
||||
}
|
|
@ -21,6 +21,7 @@ import com.anytypeio.anytype.core_ui.reactive.clicks
|
|||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetFragment
|
||||
import com.anytypeio.anytype.core_utils.ui.showMessageSnackBar
|
||||
import com.anytypeio.anytype.presentation.keychain.KeychainPhraseViewModel
|
||||
import com.anytypeio.anytype.presentation.keychain.KeychainPhraseViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.keychain.KeychainViewState
|
||||
|
@ -46,6 +47,7 @@ abstract class BaseMnemonicFragment<T : ViewBinding> : BaseBottomSheetFragment<T
|
|||
}
|
||||
|
||||
protected abstract val keychain: TextView
|
||||
protected abstract val anchor: View
|
||||
protected abstract val btnCopy: TextView
|
||||
|
||||
@Inject
|
||||
|
@ -118,7 +120,9 @@ abstract class BaseMnemonicFragment<T : ViewBinding> : BaseBottomSheetFragment<T
|
|||
keychainPhrase
|
||||
)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
toast("Recovery phrase copied to clipboard.")
|
||||
dialog?.window
|
||||
?.decorView
|
||||
?.showMessageSnackBar(getString(R.string.recovery_phrase_copied), anchor)
|
||||
} catch (e: Exception) {
|
||||
toast("Could not copy your recovery phrase. Please try again later, or copy it manually.")
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ class DashboardMnemonicReminderDialog :
|
|||
}
|
||||
|
||||
override val keychain: TextView by lazy { binding.keychain }
|
||||
override val anchor: View by lazy { binding.anchor }
|
||||
override val btnCopy: TextView by lazy { binding.btnCopy }
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -49,6 +49,7 @@ import com.anytypeio.anytype.BuildConfig
|
|||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.core_ui.extensions.addTextFromSelectedStart
|
||||
import com.anytypeio.anytype.core_ui.extensions.color
|
||||
|
@ -83,13 +84,16 @@ import com.anytypeio.anytype.core_utils.ext.gone
|
|||
import com.anytypeio.anytype.core_utils.ext.hide
|
||||
import com.anytypeio.anytype.core_utils.ext.hideSoftInput
|
||||
import com.anytypeio.anytype.core_utils.ext.invisible
|
||||
import com.anytypeio.anytype.core_utils.ext.safeNavigate
|
||||
import com.anytypeio.anytype.core_utils.ext.screen
|
||||
import com.anytypeio.anytype.core_utils.ext.show
|
||||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
import com.anytypeio.anytype.core_utils.ext.syncTranslationWithImeVisibility
|
||||
import com.anytypeio.anytype.core_utils.ext.throttleFirst
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseFragment
|
||||
import com.anytypeio.anytype.core_utils.ui.showActionableSnackBar
|
||||
import com.anytypeio.anytype.databinding.FragmentEditorBinding
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.ext.extractMarks
|
||||
|
@ -99,9 +103,6 @@ import com.anytypeio.anytype.presentation.editor.EditorViewModelFactory
|
|||
import com.anytypeio.anytype.presentation.editor.Snack
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Command
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_utils.ext.safeNavigate
|
||||
import com.anytypeio.anytype.core_utils.ext.throttleFirst
|
||||
import com.anytypeio.anytype.presentation.editor.editor.ViewState
|
||||
import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState
|
||||
import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState.Toolbar.Main
|
||||
|
@ -679,14 +680,14 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
binding.undoRedoToolbar.undo.clicks()
|
||||
.throttleFirst()
|
||||
.onEach {
|
||||
vm.onActionUndoClicked()
|
||||
}.launchIn(lifecycleScope)
|
||||
vm.onActionUndoClicked()
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
binding.undoRedoToolbar.redo.clicks()
|
||||
.throttleFirst()
|
||||
.onEach {
|
||||
vm.onActionRedoClicked()
|
||||
}.launchIn(lifecycleScope)
|
||||
vm.onActionRedoClicked()
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
lifecycleScope.subscribe(binding.styleToolbarMain.styles) {
|
||||
vm.onUpdateTextBlockStyle(it)
|
||||
|
@ -1089,6 +1090,18 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
fr.show(childFragmentManager, null)
|
||||
}
|
||||
}
|
||||
is Command.OpenObjectSnackbar -> {
|
||||
val from = (blockAdapter.views
|
||||
.firstOrNull { it is BlockView.TextSupport } as? BlockView.TextSupport)
|
||||
?.text
|
||||
binding.root.showActionableSnackBar(from, command.text, command.icon) {
|
||||
if (command.isSet) {
|
||||
vm.proceedWithOpeningSet(command.id)
|
||||
} else {
|
||||
vm.proceedWithOpeningPage(command.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
is Command.OpenLinkToScreen -> {
|
||||
jobs += lifecycleScope.launch {
|
||||
hideSoftInput()
|
||||
|
@ -1982,10 +1995,19 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
)
|
||||
}
|
||||
|
||||
override fun onMoveTo(target: Id, blocks: List<Id>) {
|
||||
override fun onMoveTo(
|
||||
target: Id,
|
||||
blocks: List<Id>,
|
||||
text: String,
|
||||
icon: ObjectIcon,
|
||||
isSet: Boolean
|
||||
) {
|
||||
vm.proceedWithMoveToAction(
|
||||
target = target,
|
||||
blocks = blocks
|
||||
text = text,
|
||||
icon = icon,
|
||||
blocks = blocks,
|
||||
isSet = isSet
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1997,11 +2019,21 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
)
|
||||
}
|
||||
|
||||
override fun onLinkTo(link: Id, target: Id, isBookmark: Boolean) {
|
||||
override fun onLinkTo(
|
||||
link: Id,
|
||||
target: Id,
|
||||
isBookmark: Boolean,
|
||||
text: String,
|
||||
icon: ObjectIcon,
|
||||
isSet: Boolean
|
||||
) {
|
||||
vm.proceedWithLinkToAction(
|
||||
link = link,
|
||||
target = target,
|
||||
isBookmark = isBookmark
|
||||
text = text,
|
||||
icon = icon,
|
||||
isBookmark = isBookmark,
|
||||
isSet = isSet
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import com.anytypeio.anytype.databinding.FragmentObjectSearchBinding
|
|||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.linking.LinkToObjectViewModel
|
||||
import com.anytypeio.anytype.presentation.linking.LinkToObjectViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchView
|
||||
import com.anytypeio.anytype.ui.search.ObjectSearchFragment
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
|
@ -182,7 +183,10 @@ class LinkToObjectFragment : BaseBottomSheetTextInputFragment<FragmentObjectSear
|
|||
onLinkTo(
|
||||
link = command.link,
|
||||
target = target,
|
||||
isBookmark = command.isBookmark
|
||||
text = command.text,
|
||||
icon = command.icon,
|
||||
isBookmark = command.isBookmark,
|
||||
isSet = command.isSet
|
||||
)
|
||||
}
|
||||
dismiss()
|
||||
|
@ -266,6 +270,13 @@ class LinkToObjectFragment : BaseBottomSheetTextInputFragment<FragmentObjectSear
|
|||
}
|
||||
|
||||
interface OnLinkToAction {
|
||||
fun onLinkTo(link: Id, target: Id, isBookmark: Boolean)
|
||||
fun onLinkTo(
|
||||
link: Id,
|
||||
target: Id,
|
||||
isBookmark: Boolean,
|
||||
text: String,
|
||||
icon: ObjectIcon,
|
||||
isSet: Boolean
|
||||
)
|
||||
fun onLinkToClose(block: Id, position: Int?)
|
||||
}
|
|
@ -18,6 +18,7 @@ import androidx.recyclerview.widget.DividerItemDecoration
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_ui.features.navigation.DefaultObjectViewAdapter
|
||||
import com.anytypeio.anytype.core_utils.ext.*
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetTextInputFragment
|
||||
|
@ -26,6 +27,7 @@ import com.anytypeio.anytype.di.common.componentManager
|
|||
import com.anytypeio.anytype.presentation.moving.MoveToView
|
||||
import com.anytypeio.anytype.presentation.moving.MoveToViewModel
|
||||
import com.anytypeio.anytype.presentation.moving.MoveToViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -179,8 +181,11 @@ class MoveToFragment : BaseBottomSheetTextInputFragment<FragmentObjectSearchBind
|
|||
}
|
||||
withParent<OnMoveToAction> {
|
||||
onMoveTo(
|
||||
target = command.target,
|
||||
blocks = blocks
|
||||
target = command.view.id,
|
||||
text = command.view.name,
|
||||
icon = command.view.icon,
|
||||
blocks = blocks,
|
||||
isSet = command.view.layout == ObjectType.Layout.SET
|
||||
)
|
||||
}
|
||||
hideSoftInput()
|
||||
|
@ -275,6 +280,6 @@ class MoveToFragment : BaseBottomSheetTextInputFragment<FragmentObjectSearchBind
|
|||
}
|
||||
|
||||
interface OnMoveToAction {
|
||||
fun onMoveTo(target: Id, blocks: List<Id>)
|
||||
fun onMoveTo(target: Id, blocks: List<Id>, text: String, icon: ObjectIcon, isSet: Boolean)
|
||||
fun onMoveToClose(blocks: List<Id>, restorePosition: Int?, restoreBlock: Id?)
|
||||
}
|
|
@ -35,6 +35,7 @@ class KeychainPhraseDialog : BaseMnemonicFragment<DialogKeychainPhraseBinding>()
|
|||
)
|
||||
|
||||
override val keychain: TextView by lazy { binding.keychain }
|
||||
override val anchor: View by lazy { binding.anchor }
|
||||
override val btnCopy: TextView by lazy { binding.btnCopy }
|
||||
|
||||
companion object {
|
||||
|
|
13
app/src/main/res/drawable/snackbar_background.xml
Normal file
13
app/src/main/res/drawable/snackbar_background.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:bottom="48dp"
|
||||
android:left="48dp"
|
||||
android:right="48dp"
|
||||
android:top="48dp">
|
||||
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/white" />
|
||||
<corners android:radius="12dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
10
app/src/main/res/drawable/snackbar_check_mark.xml
Normal file
10
app/src/main/res/drawable/snackbar_check_mark.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M16.633,4.402L9.131,16.191L3.47,10.53L4.53,9.469L8.869,13.808L15.367,3.597L16.633,4.402Z"
|
||||
android:fillColor="#2AA7EE"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/snackbar_shadow.9.png
Normal file
BIN
app/src/main/res/drawable/snackbar_shadow.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
|
@ -28,7 +28,7 @@
|
|||
android:layout_marginEnd="20dp"
|
||||
android:text="@string/do_not_forget_mnemonic_phrase"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/drag" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/drag" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
|
@ -80,4 +80,12 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/keychain" />
|
||||
|
||||
<View
|
||||
android:id="@+id/anchor"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -77,4 +77,12 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/keychain" />
|
||||
|
||||
<View
|
||||
android:id="@+id/anchor"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
66
app/src/main/res/layout/snackbar_actionable.xml
Normal file
66
app/src/main/res/layout/snackbar_actionable.xml
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/snackbar_background"
|
||||
android:foreground="@drawable/snackbar_shadow">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/snackbar_text"
|
||||
style="@style/SnackbarTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="77dp"
|
||||
android:layout_marginTop="59dp"
|
||||
android:layout_marginEnd="9dp"
|
||||
android:layout_marginBottom="59dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="linked to" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/dp_16"
|
||||
android:layout_height="@dimen/dp_16"
|
||||
android:layout_gravity="center"
|
||||
android:foregroundGravity="center"
|
||||
android:visibility="gone"
|
||||
app:emojiSize="@dimen/dp_16"
|
||||
app:imageSize="@dimen/dp_16"
|
||||
app:layout_constraintBottom_toBottomOf="@id/snackbar_text"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.6"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/snackbar_text" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/snackbar_action"
|
||||
style="@style/SnackbarTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="59dp"
|
||||
android:layout_marginEnd="77dp"
|
||||
android:layout_marginBottom="59dp"
|
||||
android:background="?selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:ellipsize="end"
|
||||
android:focusable="true"
|
||||
android:maxLines="1"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/snackbar_text"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/icon"
|
||||
app:layout_constraintTop_toTopOf="@id/snackbar_text"
|
||||
tools:text="Untitled" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
39
app/src/main/res/layout/snackbar_message.xml
Normal file
39
app/src/main/res/layout/snackbar_message.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@drawable/snackbar_background"
|
||||
android:foreground="@drawable/snackbar_shadow">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/snackbar_text"
|
||||
style="@style/SnackbarTextStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="97dp"
|
||||
android:layout_marginTop="59dp"
|
||||
android:layout_marginEnd="77dp"
|
||||
android:layout_marginBottom="59dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@string/recovery_phrase_copied" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:src="@drawable/snackbar_check_mark"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/snackbar_text"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -293,4 +293,7 @@ Do the computation of an expensive paragraph of text on a background thread:
|
|||
<item quantity="one">%d object selected</item>
|
||||
<item quantity="other">%d objects selected</item>
|
||||
</plurals>
|
||||
|
||||
<string name="snack_link_to">linked to</string>
|
||||
<string name="recovery_phrase_copied">Recovery phrase copied</string>
|
||||
</resources>
|
||||
|
|
|
@ -74,7 +74,7 @@ class PageLinksAdapter(
|
|||
}
|
||||
|
||||
class DefaultObjectViewAdapter(
|
||||
private val onClick: (Id, ObjectType.Layout?) -> Unit
|
||||
private val onClick: (DefaultObjectView) -> Unit
|
||||
) : ListAdapter<DefaultObjectView, DefaultObjectViewAdapter.ObjectViewHolder>(Differ) {
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
|
@ -86,7 +86,7 @@ class DefaultObjectViewAdapter(
|
|||
itemView.setOnClickListener {
|
||||
val pos = bindingAdapterPosition
|
||||
if (pos != RecyclerView.NO_POSITION) {
|
||||
onClick(getItem(pos).id, getItem(pos).layout)
|
||||
onClick(getItem(pos))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1041,6 +1041,12 @@
|
|||
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||
</style>
|
||||
|
||||
<style name="SnackbarTextStyle">
|
||||
<item name="android:fontFamily">@font/inter_medium</item>
|
||||
<item name="android:textSize">13sp</item>
|
||||
<item name="android:textColor">@color/text_primary</item>
|
||||
</style>
|
||||
|
||||
<!-- Editor, object link as text block, {root {guideline , iconObjectContainer, text, tvObjectType, tvDescription}}-->
|
||||
<style name="ObjectLinkBlockTextStyle">
|
||||
<item name="android:background">@null</item>
|
||||
|
|
|
@ -13,7 +13,7 @@ ext {
|
|||
|
||||
// Other Android framework dependencies
|
||||
appcompat_version = '1.3.0'
|
||||
constraintLayout_version = '2.1.3'
|
||||
constraintLayout_version = '2.1.4'
|
||||
recyclerview_version = '1.2.1'
|
||||
cardview_version = '1.0.0'
|
||||
material_version = '1.3.0'
|
||||
|
|
|
@ -185,6 +185,7 @@ import com.anytypeio.anytype.presentation.mapper.toObjectTypeView
|
|||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
|
||||
import com.anytypeio.anytype.presentation.navigation.SupportNavigation
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectTypeView
|
||||
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
|
||||
import com.anytypeio.anytype.presentation.objects.toView
|
||||
|
@ -4043,7 +4044,7 @@ class EditorViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
private fun proceedWithOpeningPage(target: Id) {
|
||||
fun proceedWithOpeningPage(target: Id) {
|
||||
viewModelScope.launch {
|
||||
closePage(CloseBlock.Params(context)).process(
|
||||
failure = {
|
||||
|
@ -4057,7 +4058,7 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedWithOpeningSet(target: Id, isPopUpToDashboard: Boolean = false) {
|
||||
fun proceedWithOpeningSet(target: Id, isPopUpToDashboard: Boolean = false) {
|
||||
viewModelScope.launch {
|
||||
closePage(CloseBlock.Params(context)).process(
|
||||
failure = {
|
||||
|
@ -4977,7 +4978,13 @@ class EditorViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
fun proceedWithMoveToAction(target: Id, blocks: List<Id>) {
|
||||
fun proceedWithMoveToAction(
|
||||
target: Id,
|
||||
text: String,
|
||||
icon: ObjectIcon,
|
||||
blocks: List<Id>,
|
||||
isSet: Boolean
|
||||
) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.d("onMoveToTargetClicked, target:[$target], blocks:[$blocks]")
|
||||
}
|
||||
|
@ -4993,7 +5000,10 @@ class EditorViewModel(
|
|||
target = "",
|
||||
targetContext = target,
|
||||
blocks = blocks,
|
||||
position = Position.BOTTOM
|
||||
position = Position.BOTTOM,
|
||||
onSuccess = {
|
||||
dispatch(Command.OpenObjectSnackbar(id = target, text, icon, isSet))
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -5053,7 +5063,14 @@ class EditorViewModel(
|
|||
dispatch(Command.OpenLinkToScreen(target = block, position = position))
|
||||
}
|
||||
|
||||
fun proceedWithLinkToAction(link: Id, target: Id, isBookmark: Boolean) {
|
||||
fun proceedWithLinkToAction(
|
||||
link: Id,
|
||||
target: Id,
|
||||
isBookmark: Boolean,
|
||||
text: String,
|
||||
icon: ObjectIcon,
|
||||
isSet: Boolean
|
||||
) {
|
||||
val targetBlock = blocks.firstOrNull { it.id == target }
|
||||
if (targetBlock != null) {
|
||||
val targetContent = targetBlock.content
|
||||
|
@ -5071,7 +5088,10 @@ class EditorViewModel(
|
|||
prototype = if (isBookmark)
|
||||
Prototype.Bookmark.Existing(target = link)
|
||||
else
|
||||
Prototype.Link(target = link)
|
||||
Prototype.Link(target = link),
|
||||
onSuccess = {
|
||||
dispatch(Command.OpenObjectSnackbar(id = link, text, icon, isSet))
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.SmartBlockType
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.core_utils.ext.Mimetype
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
|
||||
sealed class Command {
|
||||
|
||||
|
@ -33,6 +34,13 @@ sealed class Command {
|
|||
val uri: String
|
||||
) : Command()
|
||||
|
||||
data class OpenObjectSnackbar(
|
||||
val id: Id,
|
||||
val text: String,
|
||||
val icon: ObjectIcon,
|
||||
val isSet: Boolean,
|
||||
) : Command()
|
||||
|
||||
object PopBackStack : Command()
|
||||
|
||||
object ShowKeyboard : Command()
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.os.Parcelable
|
|||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.core_utils.ext.Mimetype
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
@ -28,7 +29,8 @@ sealed class Intent {
|
|||
val target: Id,
|
||||
val targetContext: Id,
|
||||
val blocks: List<Id>,
|
||||
val position: Position
|
||||
val position: Position,
|
||||
val onSuccess: (() -> Unit)? = null
|
||||
) : Document()
|
||||
|
||||
class TurnIntoDocument(
|
||||
|
@ -60,7 +62,8 @@ sealed class Intent {
|
|||
val context: Id,
|
||||
val target: Id,
|
||||
val position: Position,
|
||||
val prototype: Block.Prototype
|
||||
val prototype: Block.Prototype,
|
||||
val onSuccess: (() -> Unit)? = null
|
||||
) : CRUD()
|
||||
|
||||
class Duplicate(
|
||||
|
|
|
@ -111,6 +111,7 @@ class Orchestrator(
|
|||
val middlewareTime = System.currentTimeMillis()
|
||||
stores.focus.update(Focus.id(id = id))
|
||||
proxies.payloads.send(payload)
|
||||
intent.onSuccess?.invoke()
|
||||
analytics.sendAnalyticsCreateBlockEvent(
|
||||
prototype = intent.prototype,
|
||||
startTime = startTime,
|
||||
|
@ -408,6 +409,7 @@ class Orchestrator(
|
|||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = {
|
||||
intent.onSuccess?.invoke()
|
||||
proxies.payloads.send(it)
|
||||
analytics.sendAnalyticsReorderBlockEvent(intent.blocks.size)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
|
|||
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchViewModel
|
||||
|
@ -36,13 +38,16 @@ class LinkToObjectViewModel(
|
|||
keys = ObjectSearchConstants.defaultKeys
|
||||
)
|
||||
|
||||
override fun onObjectClicked(target: Id, layout: ObjectType.Layout?) {
|
||||
sendSearchResultEvent(target)
|
||||
override fun onObjectClicked(view: DefaultObjectView) {
|
||||
sendSearchResultEvent(view.id)
|
||||
viewModelScope.launch {
|
||||
commands.emit(
|
||||
Command.Link(
|
||||
link = target,
|
||||
isBookmark = layout == ObjectType.Layout.BOOKMARK
|
||||
link = view.id,
|
||||
text = view.name,
|
||||
icon = view.icon,
|
||||
isBookmark = view.layout == ObjectType.Layout.BOOKMARK,
|
||||
isSet = view.layout == ObjectType.Layout.SET
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -64,6 +69,12 @@ class LinkToObjectViewModel(
|
|||
|
||||
sealed class Command {
|
||||
object Exit : Command()
|
||||
data class Link(val link: Id, val isBookmark: Boolean) : Command()
|
||||
data class Link(
|
||||
val link: Id,
|
||||
val isBookmark: Boolean,
|
||||
val text: String,
|
||||
val icon: ObjectIcon,
|
||||
val isSet: Boolean
|
||||
) : Command()
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import com.anytypeio.anytype.domain.search.SearchObjects
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchQueryEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchResultEvent
|
||||
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
|
||||
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
|
||||
import com.anytypeio.anytype.presentation.objects.toView
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
|
@ -127,11 +128,11 @@ class MoveToViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
fun onObjectClicked(target: Id, layout: ObjectType.Layout?) {
|
||||
fun onObjectClicked(view: DefaultObjectView) {
|
||||
viewModelScope.launch {
|
||||
commands.emit(Command.Move(target = target))
|
||||
commands.emit(Command.Move(view = view))
|
||||
}
|
||||
sendSearchResultEvent(target)
|
||||
sendSearchResultEvent(view.id)
|
||||
}
|
||||
|
||||
fun onDialogCancelled() {
|
||||
|
@ -153,7 +154,7 @@ class MoveToViewModel(
|
|||
|
||||
sealed class Command {
|
||||
object Exit : Command()
|
||||
data class Move(val target: Id) : Command()
|
||||
data class Move(val view: DefaultObjectView) : Command()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
|
|||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchQueryEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchResultEvent
|
||||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
|
||||
import com.anytypeio.anytype.presentation.navigation.SupportNavigation
|
||||
import com.anytypeio.anytype.presentation.objects.toView
|
||||
import kotlinx.coroutines.Job
|
||||
|
@ -120,9 +121,10 @@ open class ObjectSearchViewModel(
|
|||
userInput.value = searchText
|
||||
}
|
||||
|
||||
open fun onObjectClicked(target: Id, layout: ObjectType.Layout?) {
|
||||
open fun onObjectClicked(view: DefaultObjectView) {
|
||||
val target = view.id
|
||||
sendSearchResultEvent(target)
|
||||
when (layout) {
|
||||
when (view.layout) {
|
||||
ObjectType.Layout.PROFILE,
|
||||
ObjectType.Layout.BASIC,
|
||||
ObjectType.Layout.TODO,
|
||||
|
@ -136,7 +138,7 @@ open class ObjectSearchViewModel(
|
|||
navigate(EventWrapper(AppNavigation.Command.LaunchObjectSet(target = target)))
|
||||
}
|
||||
else -> {
|
||||
Timber.e("Unexpected layout: $layout")
|
||||
Timber.e("Unexpected layout: ${view.layout}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue