mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3185 File as Object | New layout ui, part 1 (#1947)
This commit is contained in:
parent
4f60643653
commit
d979ff0e25
44 changed files with 876 additions and 607 deletions
|
@ -19,6 +19,7 @@ import com.anytypeio.anytype.core_models.Position
|
|||
import com.anytypeio.anytype.core_models.Relation
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.StubBookmark
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_ui.features.editor.slash.holders.MainMenuHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.slash.holders.MediaMenuHolder
|
||||
import com.anytypeio.anytype.domain.block.interactor.CreateBlock
|
||||
|
@ -526,14 +527,9 @@ class SlashWidgetTesting : EditorTestSetup() {
|
|||
val paragraph = paragraph(text = "FooBar")
|
||||
val paragraph2 = paragraph(text = "Second")
|
||||
|
||||
val file = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.File(
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.EMPTY
|
||||
)
|
||||
val file = StubFile(
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.EMPTY
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
|
@ -599,14 +595,9 @@ class SlashWidgetTesting : EditorTestSetup() {
|
|||
val paragraph = paragraph(text = "FooBar")
|
||||
val paragraph2 = paragraph(text = "Second")
|
||||
|
||||
val picture = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.File(
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
state = Block.Content.File.State.EMPTY
|
||||
)
|
||||
val picture = StubFile(
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
state = Block.Content.File.State.EMPTY
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
|
@ -678,14 +669,9 @@ class SlashWidgetTesting : EditorTestSetup() {
|
|||
|
||||
val paragraph2 = paragraph(text = "Second")
|
||||
|
||||
val video = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.File(
|
||||
type = Block.Content.File.Type.VIDEO,
|
||||
state = Block.Content.File.State.EMPTY
|
||||
)
|
||||
val video = StubFile(
|
||||
type = Block.Content.File.Type.VIDEO,
|
||||
state = Block.Content.File.State.EMPTY
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.anytypeio.anytype.domain.config.ConfigStorage
|
|||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.debugging.DebugAccountSelectTrace
|
||||
import com.anytypeio.anytype.domain.debugging.DebugGoroutines
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
|
@ -99,4 +100,5 @@ interface OnboardingMnemonicLoginDependencies : ComponentDependencies {
|
|||
fun spaceManager(): SpaceManager
|
||||
fun globalSubscriptionManager(): GlobalSubscriptionManager
|
||||
fun debugAccountSelectTrace(): DebugAccountSelectTrace
|
||||
fun logger(): Logger
|
||||
}
|
|
@ -25,7 +25,6 @@ import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
|||
import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import com.anytypeio.anytype.providers.DefaultUriFileProvider
|
||||
import com.anytypeio.anytype.ui.settings.space.SpaceSettingsFragment
|
||||
import dagger.Binds
|
||||
import dagger.BindsInstance
|
||||
|
|
|
@ -337,8 +337,9 @@ object DataModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideFileProvider(
|
||||
context: Context
|
||||
): UriFileProvider = DefaultUriFileProvider(context)
|
||||
context: Context,
|
||||
logger: Logger
|
||||
): UriFileProvider = DefaultUriFileProvider(context, logger)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
|
|
@ -4,19 +4,26 @@ import android.content.Context
|
|||
import android.net.Uri
|
||||
import androidx.core.content.FileProvider
|
||||
import com.anytypeio.anytype.BuildConfig
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
class DefaultUriFileProvider @Inject constructor(
|
||||
private val context: Context
|
||||
private val context: Context,
|
||||
private val logger: Logger
|
||||
) : UriFileProvider {
|
||||
|
||||
override fun getUriForFile(file: File): Uri = FileProvider.getUriForFile(
|
||||
context,
|
||||
BuildConfig.APPLICATION_ID + PROVIDER,
|
||||
file
|
||||
)
|
||||
override fun getUriForFile(file: File): Uri {
|
||||
logger.logInfo("DefaultUriFileProvider, start getting uri for file $file")
|
||||
val contentUri = FileProvider.getUriForFile(
|
||||
context,
|
||||
BuildConfig.APPLICATION_ID + PROVIDER,
|
||||
file
|
||||
)
|
||||
logger.logInfo("DefaultUriFileProvider, got uri $contentUri")
|
||||
return contentUri
|
||||
}
|
||||
}
|
||||
|
||||
private const val PROVIDER = ".provider"
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<cache-path name="." path="/" />
|
||||
<files-path name="." path="/" />
|
||||
<files-path name="file_path" path="/" />
|
||||
</paths>
|
|
@ -86,6 +86,7 @@ data class Block(
|
|||
|
||||
fun asText() = this as Text
|
||||
fun asLink() = this as Link
|
||||
fun asFile() = this as File
|
||||
|
||||
/**
|
||||
* Smart block.
|
||||
|
@ -227,12 +228,13 @@ data class Block(
|
|||
* @property state file state
|
||||
*/
|
||||
data class File(
|
||||
val targetObjectId: Id? = null,
|
||||
val name: String? = null,
|
||||
val mime: String? = null,
|
||||
val size: Long? = null,
|
||||
val type: Type? = null,
|
||||
val state: State? = null
|
||||
val targetObjectId: Id,
|
||||
val name: String,
|
||||
val mime: String,
|
||||
val size: Long,
|
||||
val type: Type,
|
||||
val state: State,
|
||||
val addedAt: Long
|
||||
) : Content() {
|
||||
enum class Type { NONE, FILE, IMAGE, VIDEO, AUDIO, PDF }
|
||||
enum class State { EMPTY, UPLOADING, DONE, ERROR }
|
||||
|
|
|
@ -75,4 +75,8 @@ object SupportedLayouts {
|
|||
fun isEditorOrFileLayout(layout: ObjectType.Layout?) : Boolean {
|
||||
return editorLayouts.contains(layout) || fileLayouts.contains(layout)
|
||||
}
|
||||
|
||||
fun isFileLayout(layout: ObjectType.Layout?) : Boolean {
|
||||
return fileLayouts.contains(layout)
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkCardSmallIco
|
|||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkCardSmallIconCoverBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkDeleteBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkLoadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockOpenFileBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockPictureBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockRelationCheckboxBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockRelationDefaultBinding
|
||||
|
@ -55,6 +56,7 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockRelationTagBinding
|
|||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTableBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTextBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleFileBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleProfileBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleTodoBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTocBinding
|
||||
|
@ -113,6 +115,8 @@ import com.anytypeio.anytype.core_ui.features.editor.holders.text.Text
|
|||
import com.anytypeio.anytype.core_ui.features.editor.holders.text.Toggle
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.upload.BookmarkUpload
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.upload.FileUpload
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.upload.OpenFile
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.upload.OpenImage
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.upload.PictureUpload
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.upload.VideoUpload
|
||||
import com.anytypeio.anytype.core_ui.features.table.holders.TableBlockHolder
|
||||
|
@ -148,6 +152,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_ERROR
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_PLACEHOLDER
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_TITLE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_UPLOAD
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_HEADER_ONE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_HEADER_THREE
|
||||
|
@ -163,6 +168,8 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_LINK_DEFAULT
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_LINK_DELETED
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_LINK_LOADING
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_BUTTON_OPEN_FILE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_BUTTON_OPEN_IMAGE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PARAGRAPH
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PICTURE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PICTURE_ERROR
|
||||
|
@ -358,6 +365,11 @@ class BlockAdapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
HOLDER_FILE_TITLE -> {
|
||||
Title.File(
|
||||
ItemBlockTitleFileBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_TODO_TITLE -> {
|
||||
Title.Todo(
|
||||
ItemBlockTitleTodoBinding.inflate(inflater, parent, false)
|
||||
|
@ -530,6 +542,12 @@ class BlockAdapter(
|
|||
ItemBlockMediaErrorBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_BUTTON_OPEN_FILE -> {
|
||||
OpenFile(ItemBlockOpenFileBinding.inflate(inflater, parent, false))
|
||||
}
|
||||
HOLDER_BUTTON_OPEN_IMAGE -> {
|
||||
OpenImage(ItemBlockOpenFileBinding.inflate(inflater, parent, false))
|
||||
}
|
||||
HOLDER_VIDEO -> {
|
||||
Video(
|
||||
ItemBlockVideoBinding.inflate(inflater, parent, false)
|
||||
|
@ -1002,6 +1020,12 @@ class BlockAdapter(
|
|||
item = blocks[position] as BlockView.Title.Todo
|
||||
)
|
||||
}
|
||||
is Title.File -> {
|
||||
holder.processPayloads(
|
||||
payloads = payloads.typeOf(),
|
||||
item = blocks[position] as BlockView.Title.File
|
||||
)
|
||||
}
|
||||
is Numbered -> {
|
||||
holder.processChangePayload(
|
||||
payloads = payloads.typeOf(),
|
||||
|
@ -1361,6 +1385,11 @@ class BlockAdapter(
|
|||
holder.content.clipboardInterceptor = clipboardInterceptor
|
||||
}
|
||||
}
|
||||
is Title.File -> {
|
||||
holder.apply {
|
||||
bind(item = blocks[position] as BlockView.Title.File,)
|
||||
}
|
||||
}
|
||||
is Code -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.Code,
|
||||
|
@ -1622,6 +1651,18 @@ class BlockAdapter(
|
|||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
is OpenFile -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.ButtonOpenFile.FileButton,
|
||||
click = onClickListener
|
||||
)
|
||||
}
|
||||
is OpenImage -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.ButtonOpenFile.ImageButton,
|
||||
click = onClickListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (holder is Text<*>) {
|
||||
|
|
|
@ -3,11 +3,10 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.other
|
|||
import android.text.Spannable
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.FrameLayout.LayoutParams
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.postDelayed
|
||||
import androidx.core.view.updateLayoutParams
|
||||
|
@ -16,6 +15,7 @@ import com.anytypeio.anytype.core_ui.R
|
|||
import com.anytypeio.anytype.core_ui.common.SearchHighlightSpan
|
||||
import com.anytypeio.anytype.core_ui.common.SearchTargetHighlightSpan
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleFileBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleProfileBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockTitleTodoBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.setBlockBackgroundColor
|
||||
|
@ -23,7 +23,7 @@ import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
|
|||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.`interface`.TextHolder
|
||||
import com.anytypeio.anytype.core_ui.tools.DefaultSpannableFactory
|
||||
import com.anytypeio.anytype.core_ui.widgets.RadialGradientComposeView
|
||||
import com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.gone
|
||||
|
@ -555,4 +555,37 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
|
|||
content.setBlockBackgroundColor(item.background)
|
||||
}
|
||||
}
|
||||
|
||||
class File(val binding: ItemBlockTitleFileBinding) : Title(binding.root) {
|
||||
|
||||
override val icon: ObjectIconWidget = binding.objectIconWidget
|
||||
override val image: ImageView = binding.cover
|
||||
override val selectionView: View = itemView
|
||||
override val root: View = itemView
|
||||
override val content: TextInputWidget = binding.title
|
||||
|
||||
init {
|
||||
icon.binding.ivImage.updateLayoutParams<LayoutParams> {
|
||||
height = itemView.resources.getDimension(R.dimen.dp_80).toInt()
|
||||
width = itemView.resources.getDimension(R.dimen.dp_64).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(
|
||||
item: BlockView.Title.File,
|
||||
) {
|
||||
super.bind(
|
||||
item = item,
|
||||
onCoverClicked = {}
|
||||
)
|
||||
icon.setIcon(item.icon)
|
||||
}
|
||||
|
||||
override fun applyTextColor(item: BlockView.Title) {
|
||||
//do nothing
|
||||
}
|
||||
override fun applyBackground(item: BlockView.Title) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.upload
|
||||
|
||||
import android.view.View
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockOpenFileBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class OpenFile(
|
||||
binding: ItemBlockOpenFileBinding
|
||||
) : BlockViewHolder(binding.root) {
|
||||
|
||||
private val root: View = itemView
|
||||
|
||||
fun bind(item: BlockView.ButtonOpenFile.FileButton, click: (ListenerType) -> Unit) {
|
||||
root.setOnClickListener {
|
||||
click(
|
||||
ListenerType.File.View(
|
||||
target = item.id,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OpenImage(
|
||||
binding: ItemBlockOpenFileBinding
|
||||
) : BlockViewHolder(binding.root) {
|
||||
|
||||
private val root: View = itemView
|
||||
|
||||
fun bind(item: BlockView.ButtonOpenFile.ImageButton, click: (ListenerType) -> Unit) {
|
||||
root.setOnClickListener {
|
||||
click(
|
||||
ListenerType.Picture.View(
|
||||
target = item.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -144,7 +144,6 @@ class ObjectIconWidget @JvmOverloads constructor(
|
|||
is ObjectIcon.None -> removeIcon()
|
||||
is ObjectIcon.File -> setFileImage(
|
||||
mime = icon.mime,
|
||||
fileName = icon.fileName,
|
||||
extension = icon.extensions
|
||||
)
|
||||
ObjectIcon.Deleted -> setDeletedIcon()
|
||||
|
@ -220,7 +219,7 @@ class ObjectIconWidget @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun setFileImage(mime: String?, fileName: String?, extension: String?) {
|
||||
private fun setFileImage(mime: String?, extension: String?) {
|
||||
val icon = mime.getMimeIcon(extension)
|
||||
with(binding) {
|
||||
ivImage.visible()
|
||||
|
|
8
core-ui/src/main/res/drawable/bg_button_open_file.xml
Normal file
8
core-ui/src/main/res/drawable/bg_button_open_file.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/shape_primary" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
7
core-ui/src/main/res/drawable/bg_title_file_icon.xml
Normal file
7
core-ui/src/main/res/drawable/bg_title_file_icon.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid
|
||||
android:color="@color/background_highlighted_medium"/>
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
23
core-ui/src/main/res/layout/item_block_open_file.xml
Normal file
23
core-ui/src/main/res/layout/item_block_open_file.xml
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileName"
|
||||
android:background="@drawable/bg_button_open_file"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginBottom="@dimen/dp_32"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="center"
|
||||
android:paddingStart="@dimen/dp_12"
|
||||
android:paddingBottom="7dp"
|
||||
android:paddingTop="7dp"
|
||||
android:paddingEnd="@dimen/dp_12"
|
||||
android:textColor="@color/text_primary"
|
||||
style="@style/TextView.UXStyle.Body.Callout.Regular"
|
||||
android:text="@string/open_file"/>
|
||||
|
||||
</FrameLayout>
|
50
core-ui/src/main/res/layout/item_block_title_file.xml
Normal file
50
core-ui/src/main/res/layout/item_block_title_file.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?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:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cover"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
android:id="@+id/objectIconWidget"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="80dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="28dp"
|
||||
android:layout_marginTop="80dp"
|
||||
app:imageSize="80dp"
|
||||
tools:src="@drawable/ic_mime_pdf"
|
||||
android:background="@drawable/bg_title_file_icon"
|
||||
android:transitionName="@string/logo_transition"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
android:id="@+id/title"
|
||||
style="@style/BlockTitleContentStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:hint="@string/untitled"
|
||||
android:paddingTop="0dp"
|
||||
app:ignoreDragAndDrop="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/objectIconWidget"
|
||||
app:onlyPasteAsPlaneText="true"
|
||||
app:layout_goneMarginTop="@dimen/dp_80"
|
||||
tools:text="Check new Android version multiline"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -35,6 +35,7 @@
|
|||
<dimen name="dp_46">46dp</dimen>
|
||||
<dimen name="dp_48">48dp</dimen>
|
||||
<dimen name="dp_54">54dp</dimen>
|
||||
<dimen name="dp_64">64dp</dimen>
|
||||
<dimen name="dp_72">72dp</dimen>
|
||||
<dimen name="dp_80">80dp</dimen>
|
||||
<dimen name="dp_51">51dp</dimen>
|
||||
|
|
|
@ -20,12 +20,10 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
|
||||
class CreateAccountTest {
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.anytypeio.anytype.domain.ext
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.ext.asMap
|
||||
import com.anytypeio.anytype.core_models.ext.asRender
|
||||
import com.anytypeio.anytype.core_models.ext.getChildrenIdsList
|
||||
|
@ -1096,19 +1097,9 @@ class BlockExtensionTest {
|
|||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
|
||||
val a = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.File()
|
||||
)
|
||||
val a = StubFile()
|
||||
|
||||
val b = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.File()
|
||||
)
|
||||
val b = StubFile()
|
||||
|
||||
val document = listOf(a, b)
|
||||
|
||||
|
|
|
@ -525,6 +525,7 @@
|
|||
<string name="open_source">Open source</string>
|
||||
<string name="reload_object_content">Reload object content</string>
|
||||
<string name="open_link">Open link</string>
|
||||
<string name="open_file">Open file</string>
|
||||
<string name="copy_email">Copy email</string>
|
||||
<string name="copy_phone_number">Copy phone number</string>
|
||||
<string name="send_email">Send email</string>
|
||||
|
|
|
@ -376,7 +376,8 @@ fun MBlock.toCoreModelsFile(): Block.Content.File {
|
|||
mime = content.mime,
|
||||
size = content.size,
|
||||
type = content.type.toCoreModels(),
|
||||
state = content.state.toCoreModels()
|
||||
state = content.state.toCoreModels(),
|
||||
addedAt = content.addedAt
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.Routes.objDate
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.searchScreenShow
|
||||
import com.anytypeio.anytype.analytics.base.EventsPropertiesKey
|
||||
import com.anytypeio.anytype.analytics.base.sendEvent
|
||||
|
@ -22,7 +21,6 @@ import com.anytypeio.anytype.core_models.InternalFlags
|
|||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.Marketplace.COLLECTION_MARKETPLACE_ID
|
||||
import com.anytypeio.anytype.core_models.Marketplace.SET_MARKETPLACE_ID
|
||||
import com.anytypeio.anytype.core_models.MarketplaceObjectTypeIds
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeIds
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeUniqueKeys
|
||||
|
@ -83,7 +81,6 @@ import com.anytypeio.anytype.domain.event.interactor.SpaceSyncAndP2PStatusProvid
|
|||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetImageIcon
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
|
||||
import com.anytypeio.anytype.domain.library.StoreSearchByIdsParams
|
||||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
|
@ -223,7 +220,6 @@ import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectShowEvent
|
|||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectTypeSelectOrChangeEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsOpenAsObject
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchResultEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchWordsEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSelectTemplateEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSelectionMenuEvent
|
||||
|
@ -233,7 +229,6 @@ import com.anytypeio.anytype.presentation.extension.sendAnalyticsSlashMenuEvent
|
|||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsStyleMenuEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsUpdateTextMarkupEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendHideKeyboardEvent
|
||||
import com.anytypeio.anytype.presentation.home.HomeScreenViewModel.Companion.HOME_SCREEN_PROFILE_OBJECT_SUBSCRIPTION
|
||||
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
|
||||
import com.anytypeio.anytype.presentation.home.navigation
|
||||
import com.anytypeio.anytype.presentation.mapper.mark
|
||||
|
@ -259,13 +254,13 @@ import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.O
|
|||
import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.OnDateSelected
|
||||
import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.OnTodayClick
|
||||
import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.OnTomorrowClick
|
||||
import com.anytypeio.anytype.presentation.extension.getFileDetailsForBlock
|
||||
import com.anytypeio.anytype.presentation.extension.getUrlForFileContent
|
||||
import com.anytypeio.anytype.presentation.objects.getCreateObjectParams
|
||||
import com.anytypeio.anytype.presentation.objects.getObjectTypeViewsForSBPage
|
||||
import com.anytypeio.anytype.presentation.objects.getProperType
|
||||
import com.anytypeio.anytype.presentation.objects.isTemplatesAllowed
|
||||
import com.anytypeio.anytype.presentation.objects.toViews
|
||||
import com.anytypeio.anytype.presentation.profile.ProfileIconView
|
||||
import com.anytypeio.anytype.presentation.profile.profileIcon
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
|
||||
import com.anytypeio.anytype.presentation.relations.getNotIncludedRecommendedRelations
|
||||
import com.anytypeio.anytype.presentation.relations.getObjectRelations
|
||||
|
@ -296,8 +291,6 @@ import kotlinx.coroutines.flow.debounce
|
|||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -366,8 +359,6 @@ class EditorViewModel(
|
|||
|
||||
val actions = MutableStateFlow(ActionItemType.defaultSorting)
|
||||
|
||||
val icon = MutableStateFlow<ProfileIconView>(ProfileIconView.Loading)
|
||||
|
||||
val isUndoEnabled = MutableStateFlow(false)
|
||||
val isRedoEnabled = MutableStateFlow(false)
|
||||
val isUndoRedoToolbarIsVisible = MutableStateFlow(false)
|
||||
|
@ -442,7 +433,6 @@ class EditorViewModel(
|
|||
init {
|
||||
Timber.i("EditorViewModel, init")
|
||||
proceedWithObservingPermissions()
|
||||
proceedWithObservingProfileIcon()
|
||||
startHandlingTextChanges()
|
||||
startProcessingFocusChanges()
|
||||
startProcessingControlPanelViewState()
|
||||
|
@ -489,35 +479,6 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedWithObservingProfileIcon() {
|
||||
viewModelScope.launch {
|
||||
spaceManager
|
||||
.observe()
|
||||
.flatMapLatest { config ->
|
||||
storelessSubscriptionContainer.subscribe(
|
||||
StoreSearchByIdsParams(
|
||||
space = SpaceId(config.techSpace),
|
||||
subscription = HOME_SCREEN_PROFILE_OBJECT_SUBSCRIPTION,
|
||||
targets = listOf(config.profile),
|
||||
keys = listOf(
|
||||
Relations.ID,
|
||||
Relations.NAME,
|
||||
Relations.ICON_EMOJI,
|
||||
Relations.ICON_IMAGE,
|
||||
Relations.ICON_OPTION
|
||||
)
|
||||
)
|
||||
).map { result ->
|
||||
val obj = result.firstOrNull()
|
||||
obj?.profileIcon(urlBuilder) ?: ProfileIconView.Placeholder(null)
|
||||
}
|
||||
}
|
||||
.catch { Timber.e(it, "Error while observing space icon") }
|
||||
.flowOn(dispatchers.io)
|
||||
.collect { icon.value = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPickedDocImageFromDevice(ctx: Id, path: String) {
|
||||
viewModelScope.launch {
|
||||
val obj = orchestrator.stores.details.getAsObject(ctx)
|
||||
|
@ -824,6 +785,7 @@ class EditorViewModel(
|
|||
val flags = mutableListOf<BlockViewRenderer.RenderFlag>()
|
||||
Timber.d("Rendering starting...")
|
||||
val doc = models.asMap().render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -3827,8 +3789,8 @@ class EditorViewModel(
|
|||
}
|
||||
is ListenerType.File.View -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit -> onFileClicked(clicked.target)
|
||||
EditorMode.Locked, EditorMode.Read -> onFileClicked(clicked.target)
|
||||
EditorMode.Edit -> onFileBlockClicked(clicked.target)
|
||||
EditorMode.Locked, EditorMode.Read -> onFileBlockClicked(clicked.target)
|
||||
EditorMode.Select -> onBlockMultiSelectClicked(clicked.target)
|
||||
else -> Unit
|
||||
}
|
||||
|
@ -4284,85 +4246,76 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onFileClicked(blockId: String) {
|
||||
val fileBlock = blocks.find { it.id == blockId }
|
||||
val url = urlBuilder.getUrlForFileBlock(
|
||||
fileBlock = fileBlock
|
||||
)
|
||||
if (url != null) {
|
||||
dispatch(
|
||||
Command.OpenFileByDefaultApp(
|
||||
id = blockId,
|
||||
uri = url
|
||||
)
|
||||
private fun onFileBlockClicked(blockId: String) {
|
||||
dispatch(
|
||||
Command.OpenFileByDefaultApp(
|
||||
id = blockId
|
||||
)
|
||||
} else {
|
||||
Timber.e("Block is not File or with wrong state, can't proceed with open")
|
||||
sendToast("Something went wrong. Couldn't open file.")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun startSharingFile(id: String, onDownloaded: (Uri) -> Unit = {}) {
|
||||
|
||||
Timber.d("startDownloadingFile, id:[$id]")
|
||||
|
||||
Timber.d("startSharingFile, fileBlockId: [$id]")
|
||||
sendToast("Preparing file to share...")
|
||||
|
||||
val block = blocks.firstOrNull { it.id == id }
|
||||
val content = block?.content
|
||||
val fileDetails = blocks.getFileDetailsForBlock(id, orchestrator, fieldParser) ?: return
|
||||
val (content, targetObjectId, fileName) = fileDetails
|
||||
|
||||
if (content is Content.File && content.state == Content.File.State.DONE) {
|
||||
viewModelScope.launch {
|
||||
orchestrator.proxies.intents.send(
|
||||
Media.ShareFile(
|
||||
objectId = content.targetObjectId.orEmpty(),
|
||||
name = content.name.orEmpty(),
|
||||
type = content.type,
|
||||
onDownloaded = onDownloaded
|
||||
)
|
||||
Timber.d("startSharingFile, fileObjectId: [$targetObjectId], fileName: [$fileName]")
|
||||
|
||||
viewModelScope.launch {
|
||||
orchestrator.proxies.intents.send(
|
||||
Media.ShareFile(
|
||||
objectId = targetObjectId,
|
||||
name = fileName,
|
||||
type = content.type,
|
||||
onDownloaded = onDownloaded
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.e("Block is not File or with wrong state, can't proceed with share!")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun startDownloadingFileFromBlock(blockId: Id) {
|
||||
|
||||
Timber.d("startDownloadingFile, for block:[$blockId]")
|
||||
|
||||
fun startDownloadingFileFromBlock(id: Id) {
|
||||
Timber.d("startDownloadingFile, for block:[$id]")
|
||||
sendToast("Downloading file in background...")
|
||||
|
||||
val fileBlock = blocks.firstOrNull { it.id == blockId }
|
||||
val fileContent = fileBlock?.content as? Content.File
|
||||
val url = urlBuilder.getUrlForFileBlock(fileBlock)
|
||||
|
||||
if (fileContent != null && url != null) {
|
||||
val fileDetails = blocks.getFileDetailsForBlock(id, orchestrator, fieldParser) ?: return
|
||||
val (content, targetObjectId, fileName) = fileDetails
|
||||
|
||||
val url = urlBuilder.getUrlForFileContent(
|
||||
fileContent = content,
|
||||
isOriginalImage = true
|
||||
)
|
||||
|
||||
Timber.d("startDownloadingFileFromBlock, fileObjectId: [$targetObjectId], fileName: [$fileName], url: [$url]")
|
||||
|
||||
if (url != null) {
|
||||
viewModelScope.launch {
|
||||
orchestrator.proxies.intents.send(
|
||||
Media.DownloadFile(
|
||||
url = url,
|
||||
name = fileContent.name.orEmpty(),
|
||||
type = fileContent.type
|
||||
name = fileName,
|
||||
type = content.type
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.e("Block is not File or with wrong state, can't proceed with download")
|
||||
Timber.e("Couldn't proceed with downloading file, because url is null")
|
||||
sendToast("Something went wrong. Couldn't download file.")
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithDownloadCurrentObjectAsFile() {
|
||||
|
||||
val details = orchestrator.stores.details.current()
|
||||
val objectDetails = details.details[context]?.map ?: return
|
||||
if (objectDetails.isEmpty()) return
|
||||
val obj = ObjectWrapper.Basic(objectDetails)
|
||||
val fileObject = orchestrator.stores.details.getAsObject(target = context)
|
||||
if (fileObject == null) {
|
||||
Timber.e("Object with id $context not found.")
|
||||
return
|
||||
}
|
||||
|
||||
Timber.d("startDownloadingFileAsObject, for object:[$obj]")
|
||||
Timber.d("startDownloadingFileAsObject, for object:[$context]")
|
||||
|
||||
val layout = obj.layout
|
||||
val layout = fileObject.layout
|
||||
|
||||
if (layout == null || layout !in SupportedLayouts.fileLayouts) {
|
||||
Timber.e("Object with layout:$layout is not Media, can't proceed with download")
|
||||
|
@ -4373,7 +4326,7 @@ class EditorViewModel(
|
|||
sendToast("Downloading file in background...")
|
||||
|
||||
val url = urlBuilder.getUrlBasedOnFileLayout(
|
||||
obj = obj.id,
|
||||
obj = fileObject.id,
|
||||
layout = layout
|
||||
)
|
||||
|
||||
|
@ -4382,7 +4335,7 @@ class EditorViewModel(
|
|||
orchestrator.proxies.intents.send(
|
||||
Media.DownloadFile(
|
||||
url = url,
|
||||
name = fieldParser.getObjectName(obj),
|
||||
name = fieldParser.getObjectName(fileObject),
|
||||
type = null
|
||||
)
|
||||
)
|
||||
|
|
|
@ -33,8 +33,7 @@ sealed class Command {
|
|||
* @property [id] id of the file block
|
||||
*/
|
||||
data class OpenFileByDefaultApp(
|
||||
val id: String,
|
||||
val uri: String
|
||||
val id: String
|
||||
) : Command()
|
||||
|
||||
data class OpenObjectSnackbar(
|
||||
|
|
|
@ -155,6 +155,9 @@ fun List<BlockView>.singleStylingMode(
|
|||
is BlockView.Title.Todo -> view.copy(
|
||||
mode = BlockView.Mode.READ
|
||||
)
|
||||
is BlockView.Title.File -> view.copy(
|
||||
mode = BlockView.Mode.READ
|
||||
)
|
||||
is BlockView.Title.Profile -> view.copy(
|
||||
mode = BlockView.Mode.READ
|
||||
)
|
||||
|
@ -312,6 +315,9 @@ fun List<BlockView>.enterSAM(
|
|||
is BlockView.Title.Todo -> view.copy(
|
||||
mode = BlockView.Mode.READ
|
||||
)
|
||||
is BlockView.Title.File -> view.copy(
|
||||
mode = BlockView.Mode.READ
|
||||
)
|
||||
is BlockView.Title.Archive -> view.copy(
|
||||
mode = BlockView.Mode.READ
|
||||
)
|
||||
|
@ -494,6 +500,7 @@ fun List<BlockView>.updateCursorAndEditMode(
|
|||
)
|
||||
is BlockView.Title.Basic -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.Todo -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.File -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.Profile -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.Archive -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
else -> view.also {
|
||||
|
@ -516,6 +523,7 @@ fun List<BlockView>.toReadMode(): List<BlockView> = map { view ->
|
|||
is BlockView.Text.Callout -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Title.Basic -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Title.Todo -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Title.File -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Title.Profile -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Title.Archive -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Description -> view.copy(mode = BlockView.Mode.READ)
|
||||
|
@ -585,6 +593,7 @@ fun List<BlockView>.toEditMode(): List<BlockView> = map { view ->
|
|||
is BlockView.Title.Basic -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.Profile -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.Todo -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.File -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
is BlockView.Title.Archive -> view.copy(mode = BlockView.Mode.EDIT)
|
||||
else -> view.also { check(view !is BlockView.Permission) }
|
||||
}
|
||||
|
@ -605,6 +614,7 @@ fun List<BlockView>.clearSearchHighlights(): List<BlockView> = map { view ->
|
|||
is BlockView.Title.Basic -> view.copy(searchFields = emptyList())
|
||||
is BlockView.Title.Profile -> view.copy(searchFields = emptyList())
|
||||
is BlockView.Title.Todo -> view.copy(searchFields = emptyList())
|
||||
is BlockView.Title.File -> view.copy(searchFields = emptyList())
|
||||
is BlockView.Media.Bookmark -> view.copy(searchFields = emptyList())
|
||||
is BlockView.Media.File -> view.copy(searchFields = emptyList())
|
||||
is BlockView.LinkToObject.Default.Text -> view.copy(searchFields = emptyList())
|
||||
|
@ -674,6 +684,10 @@ fun List<BlockView>.highlight(
|
|||
val fields = listOf(DEFAULT_SEARCH_FIELD_KEY to view.text.orEmpty())
|
||||
view.copy(searchFields = highlighter(fields))
|
||||
}
|
||||
is BlockView.Title.File -> {
|
||||
val fields = listOf(DEFAULT_SEARCH_FIELD_KEY to view.text.orEmpty())
|
||||
view.copy(searchFields = highlighter(fields))
|
||||
}
|
||||
is BlockView.Title.Profile -> {
|
||||
val fields = listOf(DEFAULT_SEARCH_FIELD_KEY to view.text.orEmpty())
|
||||
view.copy(searchFields = highlighter(fields))
|
||||
|
@ -781,6 +795,7 @@ fun BlockView.setHighlight(
|
|||
is BlockView.Title.Basic -> copy(searchFields = highlights)
|
||||
is BlockView.Title.Profile -> copy(searchFields = highlights)
|
||||
is BlockView.Title.Todo -> copy(searchFields = highlights)
|
||||
is BlockView.Title.File -> copy(searchFields = highlights)
|
||||
is BlockView.Media.Bookmark -> copy(searchFields = highlights)
|
||||
is BlockView.Media.File -> copy(searchFields = highlights)
|
||||
is BlockView.LinkToObject.Default.Text -> copy(searchFields = highlights)
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_ERROR
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_PLACEHOLDER
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_TITLE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_FILE_UPLOAD
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_HEADER_ONE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_HEADER_THREE
|
||||
|
@ -43,9 +44,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_LINK_DELETED
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_LINK_LOADING
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_TYPE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_TYPE_COLLECTION
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_TYPE_DELETED
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_TYPE_SET
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_BUTTON_OPEN_FILE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_BUTTON_OPEN_IMAGE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PARAGRAPH
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PICTURE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PICTURE_ERROR
|
||||
|
@ -75,7 +76,6 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.objects.appearance.choose.ObjectAppearanceChooseSettingsView
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceIconView
|
||||
|
||||
/**
|
||||
* UI-models for different types of blocks.
|
||||
|
@ -668,6 +668,31 @@ sealed class BlockView : ViewType {
|
|||
override fun getViewType() = HOLDER_TITLE
|
||||
}
|
||||
|
||||
/**
|
||||
* UI-model for a file-layout title block.
|
||||
* @property id block's id
|
||||
* @property text text content (i.e. title text)
|
||||
*/
|
||||
data class File(
|
||||
override val id: String,
|
||||
override var isFocused: Boolean = false,
|
||||
override var text: String,
|
||||
override var coverColor: CoverColor? = null,
|
||||
override var coverImage: Url? = null,
|
||||
override var coverGradient: String? = null,
|
||||
override val background: ThemeColor = ThemeColor.DEFAULT,
|
||||
override val color: ThemeColor = ThemeColor.DEFAULT,
|
||||
val emoji: String? = null,
|
||||
override val image: String? = null,
|
||||
override val mode: Mode = Mode.READ,
|
||||
override var cursor: Int? = null,
|
||||
override val searchFields: List<Searchable.Field> = emptyList(),
|
||||
override val hint: String? = null,
|
||||
val icon: ObjectIcon
|
||||
) : Title(), Searchable {
|
||||
override fun getViewType() = HOLDER_FILE_TITLE
|
||||
}
|
||||
|
||||
/**
|
||||
* UI-model for a profile-layout title block.
|
||||
* @property id block's id
|
||||
|
@ -1268,6 +1293,28 @@ sealed class BlockView : ViewType {
|
|||
override fun getViewType(): Int = HOLDER_FEATURED_RELATION
|
||||
}
|
||||
|
||||
sealed class ButtonOpenFile(
|
||||
override val id: String,
|
||||
val isSelected: Boolean = false
|
||||
) : BlockView() {
|
||||
|
||||
abstract val targetId: Id?
|
||||
|
||||
data class ImageButton(
|
||||
override val id: String,
|
||||
override val targetId: Id
|
||||
) : ButtonOpenFile(id) {
|
||||
override fun getViewType(): Int = HOLDER_BUTTON_OPEN_IMAGE
|
||||
}
|
||||
|
||||
data class FileButton(
|
||||
override val id: String,
|
||||
override val targetId: Id
|
||||
) : ButtonOpenFile(id) {
|
||||
override fun getViewType(): Int = HOLDER_BUTTON_OPEN_FILE
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Relation : BlockView(), Selectable, Indentable, Decoratable {
|
||||
|
||||
abstract val background: ThemeColor
|
||||
|
|
|
@ -5,6 +5,7 @@ object Types {
|
|||
const val HOLDER_TITLE = 1
|
||||
const val HOLDER_PROFILE_TITLE = 35
|
||||
const val HOLDER_ARCHIVE_TITLE = 36
|
||||
const val HOLDER_FILE_TITLE = 37
|
||||
const val HOLDER_TODO_TITLE = 48
|
||||
const val HOLDER_HEADER_ONE = 2
|
||||
const val HOLDER_HEADER_TWO = 3
|
||||
|
@ -45,6 +46,8 @@ object Types {
|
|||
const val HOLDER_FILE_PLACEHOLDER = 32
|
||||
const val HOLDER_FILE_UPLOAD = 33
|
||||
const val HOLDER_FILE_ERROR = 34
|
||||
const val HOLDER_BUTTON_OPEN_FILE = 134
|
||||
const val HOLDER_BUTTON_OPEN_IMAGE = 135
|
||||
|
||||
const val HOLDER_DIVIDER_LINE = 16
|
||||
const val HOLDER_DIVIDER_DOTS = 38
|
||||
|
|
|
@ -15,12 +15,14 @@ interface BlockViewRenderer {
|
|||
|
||||
/**
|
||||
* Ext. function for recursively converting map to flattened view data structure.
|
||||
* @param context object id
|
||||
* @param root root block, from which rendering starts
|
||||
* @param focus id of the current focus
|
||||
* @param anchor id of the current anchor (current rendering node)
|
||||
* @param indent current indent at this rendering node.
|
||||
*/
|
||||
suspend fun Map<Id, List<Block>>.render(
|
||||
context: Id,
|
||||
mode: EditorMode = EditorMode.Edit,
|
||||
root: Block,
|
||||
focus: Editor.Focus,
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.ObjectTypeIds.BOOKMARK
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.SupportedLayouts
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.ext.parseThemeTextColor
|
||||
import com.anytypeio.anytype.core_models.ext.textColor
|
||||
|
@ -58,6 +57,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
) : BlockViewRenderer, ToggleStateHolder by toggleStateHolder {
|
||||
|
||||
override suspend fun Map<Id, List<Block>>.render(
|
||||
context: Id,
|
||||
mode: EditorMode,
|
||||
root: Block,
|
||||
focus: Focus,
|
||||
|
@ -119,6 +119,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -164,6 +165,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -201,6 +203,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (toggleStateHolder.isToggled(block.id)) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -241,6 +244,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -281,6 +285,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -321,6 +326,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -364,6 +370,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -400,6 +407,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -458,6 +466,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -497,6 +506,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -541,6 +551,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
if (block.children.isNotEmpty()) {
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -623,11 +634,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
isPreviousBlockMedia = link is BlockView.LinkToObject.Default.Card
|
||||
}
|
||||
is Content.File -> {
|
||||
val detail = details.details.getOrDefault(root.id, Block.Fields.empty())
|
||||
val obj = ObjectWrapper.Basic(detail.map)
|
||||
if (SupportedLayouts.fileLayouts.contains(obj.layout)) {
|
||||
return@forEach
|
||||
}
|
||||
mCounter = 0
|
||||
val blockDecorationScheme = buildNestedDecorationData(
|
||||
block = block,
|
||||
|
@ -640,18 +646,19 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
background = block.parseThemeBackgroundColor()
|
||||
)
|
||||
)
|
||||
result.add(
|
||||
file(
|
||||
mode = mode,
|
||||
content = content,
|
||||
block = block,
|
||||
indent = indent,
|
||||
selection = selection,
|
||||
isPreviousBlockMedia = isPreviousBlockMedia,
|
||||
schema = blockDecorationScheme,
|
||||
details = details
|
||||
)
|
||||
val fileBlock = file(
|
||||
context = context,
|
||||
mode = mode,
|
||||
content = content,
|
||||
block = block,
|
||||
indent = indent,
|
||||
selection = selection,
|
||||
isPreviousBlockMedia = isPreviousBlockMedia,
|
||||
schema = blockDecorationScheme,
|
||||
details = details,
|
||||
fieldParser = fieldParser
|
||||
)
|
||||
result.add(fileBlock)
|
||||
isPreviousBlockMedia = true
|
||||
}
|
||||
is Content.Layout -> {
|
||||
|
@ -666,6 +673,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
}
|
||||
result.addAll(
|
||||
render(
|
||||
context = context,
|
||||
mode = mode,
|
||||
root = root,
|
||||
focus = focus,
|
||||
|
@ -1376,6 +1384,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
}
|
||||
|
||||
private fun file(
|
||||
context: Id,
|
||||
mode: EditorMode,
|
||||
content: Content.File,
|
||||
block: Block,
|
||||
|
@ -1383,99 +1392,21 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
selection: Set<Id>,
|
||||
isPreviousBlockMedia: Boolean,
|
||||
schema: NestedDecorationData,
|
||||
details: Block.Details
|
||||
): BlockView = when (content.type) {
|
||||
Content.File.Type.IMAGE -> content.toPictureView(
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
isSelected = checkIfSelected(
|
||||
mode = mode,
|
||||
block = block,
|
||||
selection = selection
|
||||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPreviousBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.FILE -> content.toFileView(
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
isSelected = checkIfSelected(
|
||||
mode = mode,
|
||||
block = block,
|
||||
selection = selection
|
||||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.VIDEO -> content.toVideoView(
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
isSelected = checkIfSelected(
|
||||
mode = mode,
|
||||
block = block,
|
||||
selection = selection
|
||||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.AUDIO -> content.toFileView(
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
isSelected = checkIfSelected(
|
||||
mode = mode,
|
||||
block = block,
|
||||
selection = selection
|
||||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.PDF -> content.toFileView(
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
isSelected = checkIfSelected(
|
||||
mode = mode,
|
||||
block = block,
|
||||
selection = selection
|
||||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.NONE -> content.toFileView(
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
isSelected = checkIfSelected(
|
||||
mode = mode,
|
||||
block = block,
|
||||
selection = selection
|
||||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected file type: ${content.type}")
|
||||
details: Block.Details,
|
||||
fieldParser: FieldParser
|
||||
): BlockView {
|
||||
|
||||
val blockViewMode =
|
||||
if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ
|
||||
val isSelected = checkIfSelected(mode, block, selection)
|
||||
val background = block.parseThemeBackgroundColor()
|
||||
val decorations = schema.toBlockViewDecoration(block)
|
||||
|
||||
return when (content.type) {
|
||||
Content.File.Type.IMAGE -> content.toPictureView(context, block.id, urlBuilder, indent, blockViewMode, isSelected, background, isPreviousBlockMedia, decorations, details, fieldParser)
|
||||
Content.File.Type.VIDEO -> content.toVideoView(context, block.id, urlBuilder, indent, blockViewMode, isSelected, background, isPreviousBlockMedia, decorations, details, fieldParser)
|
||||
else -> content.toFileView(context, block.id, urlBuilder, indent, blockViewMode, isSelected, background, isPreviousBlockMedia, decorations, details, fieldParser)
|
||||
}
|
||||
}
|
||||
|
||||
private fun title(
|
||||
|
@ -1511,7 +1442,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
|
||||
val layoutCode = details.details[root.id]?.layout?.toInt()
|
||||
|
||||
val layout = ObjectType.Layout.values().find {
|
||||
val layout = ObjectType.Layout.entries.find {
|
||||
it.code == layoutCode
|
||||
} ?: ObjectType.Layout.BASIC
|
||||
|
||||
|
@ -1572,18 +1503,32 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
)
|
||||
}
|
||||
ObjectType.Layout.FILE,
|
||||
ObjectType.Layout.IMAGE,
|
||||
ObjectType.Layout.BOOKMARK,
|
||||
ObjectType.Layout.VIDEO,
|
||||
ObjectType.Layout.AUDIO,
|
||||
ObjectType.Layout.PDF -> {
|
||||
val objFile = ObjectWrapper.Basic(details.details[root.id]?.map.orEmpty())
|
||||
BlockView.Title.File(
|
||||
mode = blockMode,
|
||||
id = block.id,
|
||||
text = content.text,
|
||||
isFocused = resolveIsFocused(focus, block),
|
||||
cursor = cursor,
|
||||
coverColor = coverContainer.coverColor,
|
||||
coverImage = coverContainer.coverImage,
|
||||
coverGradient = coverContainer.coverGradient,
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
color = block.textColor(),
|
||||
icon = objFile.objectIcon(builder = urlBuilder)
|
||||
)
|
||||
}
|
||||
ObjectType.Layout.IMAGE -> {
|
||||
BlockView.Title.Basic(
|
||||
mode = blockMode,
|
||||
id = block.id,
|
||||
text = content.text,
|
||||
emoji = details.details[root.id]?.iconEmoji?.takeIf { it.isNotBlank() },
|
||||
image = details.details[root.id]?.iconImage?.let { image ->
|
||||
if (image.isNotBlank() && layout != ObjectType.Layout.BOOKMARK)
|
||||
if (image.isNotBlank())
|
||||
urlBuilder.thumbnail(image)
|
||||
else
|
||||
null
|
||||
|
|
|
@ -283,6 +283,7 @@ fun List<BlockView>.toggleTableMode(
|
|||
is BlockView.Title.Basic -> view.copy(
|
||||
mode = cellsMode
|
||||
)
|
||||
is BlockView.Title.File -> view
|
||||
is BlockView.Title.Profile -> view.copy(
|
||||
mode = cellsMode
|
||||
)
|
||||
|
@ -352,6 +353,8 @@ fun List<BlockView>.toggleTableMode(
|
|||
is BlockView.DataView.EmptyData -> view.copy(isSelected = false)
|
||||
is BlockView.DataView.EmptySource -> view.copy(isSelected = false)
|
||||
is BlockView.DataView.Deleted -> view.copy(isSelected = false)
|
||||
is BlockView.ButtonOpenFile.ImageButton -> view
|
||||
is BlockView.ButtonOpenFile.FileButton -> view
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package com.anytypeio.anytype.presentation.extension
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Block.Content
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParser
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
|
||||
import timber.log.Timber
|
||||
|
||||
fun UrlBuilder.getUrlForFileBlock(
|
||||
fileBlock: Block?,
|
||||
|
@ -66,3 +70,52 @@ fun UrlBuilder.getUrlBasedOnFileLayout(
|
|||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data class FileDetails(
|
||||
val content: Block.Content.File,
|
||||
val targetObjectId: String,
|
||||
val fileName: String,
|
||||
)
|
||||
|
||||
/**
|
||||
* Attempts to retrieve and validate the file details for a given block [blockId].
|
||||
* Returns [FileDetails] if successful, or `null` if something went wrong.
|
||||
*/
|
||||
fun List<Block>.getFileDetailsForBlock(
|
||||
blockId: String,
|
||||
orchestrator: Orchestrator,
|
||||
fieldParser: FieldParser
|
||||
): FileDetails? {
|
||||
|
||||
val block = firstOrNull { it.id == blockId } ?: run {
|
||||
Timber.e("No block found with id $blockId")
|
||||
return null
|
||||
}
|
||||
|
||||
val content = block.content
|
||||
if (content !is Content.File || content.state != Content.File.State.DONE) {
|
||||
Timber.e("Block content is not a file or is not in the DONE state; cannot proceed.")
|
||||
return null
|
||||
}
|
||||
|
||||
val targetObjectId = content.targetObjectId
|
||||
if (targetObjectId.isEmpty()) {
|
||||
Timber.e("Target object ID is empty; cannot proceed with file sharing.")
|
||||
return null
|
||||
}
|
||||
|
||||
val fileObject = orchestrator.stores.details.getAsObject(target = targetObjectId)
|
||||
if (fileObject == null) {
|
||||
Timber.e("Object with id $targetObjectId not found.")
|
||||
return null
|
||||
}
|
||||
|
||||
val fileName = fieldParser.getObjectName(fileObject)
|
||||
|
||||
return FileDetails(
|
||||
content = content,
|
||||
targetObjectId = targetObjectId,
|
||||
fileName = fileName,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -529,6 +529,7 @@ class VersionHistoryViewModel(
|
|||
defaultPayloadConsumer(payload)
|
||||
val root = event.blocks.first { it.id == vmParams.objectId }
|
||||
val blocks = event.blocks.asMap().render(
|
||||
context = obj.id,
|
||||
mode = Mode.Read,
|
||||
root = root,
|
||||
focus = Editor.Focus.empty(),
|
||||
|
@ -566,6 +567,7 @@ class VersionHistoryViewModel(
|
|||
} else {
|
||||
val root = event.blocks.first { it.id == vmParams.objectId }
|
||||
val blocks = event.blocks.asMap().render(
|
||||
context = obj.id,
|
||||
mode = Mode.Read,
|
||||
root = root,
|
||||
focus = Editor.Focus.empty(),
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.ObjectType
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.SupportedLayouts
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.domain.config.DebugSettings
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
|
@ -31,6 +32,7 @@ import com.anytypeio.anytype.presentation.templates.TemplateObjectTypeView
|
|||
import timber.log.Timber
|
||||
|
||||
fun Block.Content.File.toPictureView(
|
||||
context: Id,
|
||||
blockId: String,
|
||||
urlBuilder: UrlBuilder,
|
||||
indent: Int,
|
||||
|
@ -39,7 +41,8 @@ fun Block.Content.File.toPictureView(
|
|||
background: ThemeColor,
|
||||
isPreviousBlockMedia: Boolean,
|
||||
decorations: List<BlockView.Decoration>,
|
||||
details: Block.Details = Block.Details()
|
||||
details: Block.Details = Block.Details(),
|
||||
fieldParser: FieldParser
|
||||
): BlockView = when (state) {
|
||||
Block.Content.File.State.EMPTY -> BlockView.MediaPlaceholder.Picture(
|
||||
id = blockId,
|
||||
|
@ -59,25 +62,32 @@ fun Block.Content.File.toPictureView(
|
|||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.DONE -> {
|
||||
val url = urlBuilder.getUrlForFileContent(this)
|
||||
val targetId = this.targetObjectId
|
||||
val struct = details.details[targetId]?.map
|
||||
if (url != null && targetId != null) {
|
||||
val targetObject = ObjectWrapper.File(struct.orEmpty())
|
||||
BlockView.Media.Picture(
|
||||
id = blockId,
|
||||
targetObjectId = targetId,
|
||||
url = url,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations,
|
||||
size = targetObject.sizeInBytes?.toLong(),
|
||||
name = targetObject.name,
|
||||
mime = targetObject.fileMimeType
|
||||
)
|
||||
|
||||
val url = urlBuilder.getUrlForFileContent(this)
|
||||
val currentObject = ObjectWrapper.Basic(details.details[context]?.map.orEmpty())
|
||||
val targetObject = ObjectWrapper.Basic(details.details[targetObjectId]?.map.orEmpty())
|
||||
|
||||
if (url != null && targetObject.isValid && targetObject.notDeletedNorArchived) {
|
||||
if (currentObject.layout == ObjectType.Layout.IMAGE) {
|
||||
BlockView.ButtonOpenFile.ImageButton(
|
||||
id = blockId,
|
||||
targetId = targetObjectId
|
||||
)
|
||||
} else {
|
||||
BlockView.Media.Picture(
|
||||
id = blockId,
|
||||
targetObjectId = targetObjectId,
|
||||
url = url,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations,
|
||||
size = targetObject.sizeInBytes?.toLong(),
|
||||
name = fieldParser.getObjectName(targetObject),
|
||||
mime = targetObject.fileMimeType
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.w("Could not build picture view for block $blockId")
|
||||
BlockView.Error.Picture(
|
||||
|
@ -99,10 +109,10 @@ fun Block.Content.File.toPictureView(
|
|||
decorations = decorations,
|
||||
name = name
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected state: $state")
|
||||
}
|
||||
|
||||
fun Block.Content.File.toVideoView(
|
||||
context: Id,
|
||||
blockId: Id,
|
||||
urlBuilder: UrlBuilder,
|
||||
indent: Int,
|
||||
|
@ -111,7 +121,8 @@ fun Block.Content.File.toVideoView(
|
|||
background: ThemeColor,
|
||||
isPrevBlockMedia: Boolean,
|
||||
decorations: List<BlockView.Decoration>,
|
||||
details: Block.Details = Block.Details()
|
||||
details: Block.Details = Block.Details(),
|
||||
fieldParser: FieldParser
|
||||
): BlockView = when (state) {
|
||||
Block.Content.File.State.EMPTY -> BlockView.MediaPlaceholder.Video(
|
||||
id = blockId,
|
||||
|
@ -131,25 +142,32 @@ fun Block.Content.File.toVideoView(
|
|||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.DONE -> {
|
||||
val url = urlBuilder.getUrlForFileContent(this)
|
||||
val targetId = this.targetObjectId
|
||||
val struct = details.details[targetId]?.map
|
||||
if (url != null && targetId != null && !struct.isNullOrEmpty()) {
|
||||
val targetObject = ObjectWrapper.File(struct)
|
||||
BlockView.Media.Video(
|
||||
id = blockId,
|
||||
targetObjectId = targetId,
|
||||
url = url,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations,
|
||||
size = targetObject.sizeInBytes?.toLong(),
|
||||
name = targetObject.name,
|
||||
mime = targetObject.fileMimeType
|
||||
)
|
||||
|
||||
val url = urlBuilder.getUrlForFileContent(this)
|
||||
val currentObject = ObjectWrapper.Basic(details.details[context]?.map.orEmpty())
|
||||
val targetObject = ObjectWrapper.Basic(details.details[targetObjectId]?.map.orEmpty())
|
||||
|
||||
if (url != null && targetObject.isValid && targetObject.notDeletedNorArchived) {
|
||||
if (currentObject.layout == ObjectType.Layout.VIDEO) {
|
||||
BlockView.ButtonOpenFile.FileButton(
|
||||
id = blockId,
|
||||
targetId = targetObjectId
|
||||
)
|
||||
} else {
|
||||
BlockView.Media.Video(
|
||||
id = blockId,
|
||||
targetObjectId = targetObjectId,
|
||||
url = url,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations,
|
||||
size = targetObject.sizeInBytes?.toLong(),
|
||||
name = fieldParser.getObjectName(targetObject),
|
||||
mime = targetObject.fileMimeType
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.w("Could not build video view for block $blockId")
|
||||
BlockView.Error.Video(
|
||||
|
@ -171,10 +189,10 @@ fun Block.Content.File.toVideoView(
|
|||
decorations = decorations,
|
||||
name = name
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected state: $state")
|
||||
}
|
||||
|
||||
fun Block.Content.File.toFileView(
|
||||
context: Id,
|
||||
blockId: String,
|
||||
urlBuilder: UrlBuilder,
|
||||
indent: Int,
|
||||
|
@ -183,7 +201,8 @@ fun Block.Content.File.toFileView(
|
|||
background: ThemeColor,
|
||||
isPrevBlockMedia: Boolean,
|
||||
decorations: List<BlockView.Decoration>,
|
||||
details: Block.Details = Block.Details()
|
||||
details: Block.Details = Block.Details(),
|
||||
fieldParser: FieldParser
|
||||
): BlockView = when (state) {
|
||||
Block.Content.File.State.EMPTY -> BlockView.MediaPlaceholder.File(
|
||||
id = blockId,
|
||||
|
@ -203,24 +222,21 @@ fun Block.Content.File.toFileView(
|
|||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.DONE -> {
|
||||
|
||||
val url = urlBuilder.getUrlForFileContent(this)
|
||||
val targetId = this.targetObjectId
|
||||
val struct = details.details[targetId]?.map
|
||||
if (url != null && targetId != null) {
|
||||
if (struct.isNullOrEmpty()) {
|
||||
BlockView.Upload.File(
|
||||
val currentObject = ObjectWrapper.Basic(details.details[context]?.map.orEmpty())
|
||||
val targetObject = ObjectWrapper.Basic(details.details[targetObjectId]?.map.orEmpty())
|
||||
|
||||
if (url != null && targetObject.isValid && targetObject.notDeletedNorArchived) {
|
||||
if (SupportedLayouts.fileLayouts.contains(currentObject.layout)) {
|
||||
BlockView.ButtonOpenFile.FileButton(
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
targetId = targetObjectId
|
||||
)
|
||||
} else {
|
||||
val targetObject = ObjectWrapper.File(struct)
|
||||
BlockView.Media.File(
|
||||
id = blockId,
|
||||
targetObjectId = targetId,
|
||||
targetObjectId = targetObjectId,
|
||||
url = url,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
|
@ -228,7 +244,7 @@ fun Block.Content.File.toFileView(
|
|||
background = background,
|
||||
decorations = decorations,
|
||||
size = targetObject.sizeInBytes?.toLong(),
|
||||
name = targetObject.name,
|
||||
name = fieldParser.getObjectName(targetObject),
|
||||
mime = targetObject.fileMimeType,
|
||||
fileExt = targetObject.fileExt
|
||||
)
|
||||
|
@ -254,7 +270,6 @@ fun Block.Content.File.toFileView(
|
|||
decorations = decorations,
|
||||
name = name
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected state: $state")
|
||||
}
|
||||
|
||||
fun Block.Align.toView(): Alignment = when (this) {
|
||||
|
|
|
@ -94,6 +94,7 @@ class TemplateBlankViewModel(
|
|||
|
||||
viewModelScope.launch {
|
||||
state.value = page.asMap().render(
|
||||
context = DEFAULT_TEMPLATE_ID_BLANK,
|
||||
mode = Editor.Mode.Read,
|
||||
root = page.first(),
|
||||
focus = com.anytypeio.anytype.domain.editor.Editor.Focus.empty(),
|
||||
|
|
|
@ -76,6 +76,7 @@ class DefaultBlockViewRendererTest {
|
|||
details: Block.Details,
|
||||
schema: NestedDecorationData = emptyList()
|
||||
): List<BlockView> = blocks.render(
|
||||
context = root.id,
|
||||
root = root,
|
||||
focus = focus,
|
||||
anchor = anchor,
|
||||
|
@ -5754,24 +5755,38 @@ class DefaultBlockViewRendererTest {
|
|||
//endregion
|
||||
|
||||
@Test
|
||||
fun `should not render file block in case of file layout`() {
|
||||
|
||||
val file = StubFile(
|
||||
backgroundColor = null,
|
||||
state = Block.Content.File.State.DONE,
|
||||
type = Block.Content.File.Type.FILE
|
||||
fun `should render file open block in case of file, pdf, audio or video layouts`(){
|
||||
val fileTypeExceptImage = listOf(
|
||||
Block.Content.File.Type.FILE to Layout.FILE,
|
||||
Block.Content.File.Type.PDF to Layout.PDF,
|
||||
Block.Content.File.Type.VIDEO to Layout.VIDEO,
|
||||
Block.Content.File.Type.AUDIO to Layout.AUDIO,
|
||||
)
|
||||
|
||||
fileTypeExceptImage.forEach { (fileType, layout) ->
|
||||
testFileLayout(type = fileType, layout = layout)
|
||||
}
|
||||
}
|
||||
|
||||
private fun testFileLayout(type: Block.Content.File.Type, layout: Layout) {
|
||||
|
||||
val currentObjectId = MockDataFactory.randomUuid()
|
||||
|
||||
val file = StubFile(type = type, targetObjectId = currentObjectId)
|
||||
|
||||
val paragraph = StubParagraph()
|
||||
|
||||
val page = StubSmartBlock(children = listOf(paragraph.id, file.id))
|
||||
val page = StubSmartBlock(id = currentObjectId, children = listOf(paragraph.id, file.id))
|
||||
|
||||
val details = mapOf(page.id to Block.Fields(
|
||||
mapOf(
|
||||
Relations.NAME to "file-name",
|
||||
Relations.LAYOUT to Layout.FILE.code.toDouble()
|
||||
val details = mapOf(
|
||||
page.id to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to currentObjectId,
|
||||
Relations.NAME to "file-name",
|
||||
Relations.LAYOUT to layout.code.toDouble()
|
||||
)
|
||||
)
|
||||
))
|
||||
)
|
||||
|
||||
val blocks = listOf(page, paragraph, file)
|
||||
|
||||
|
@ -5806,6 +5821,78 @@ class DefaultBlockViewRendererTest {
|
|||
background = paragraph.parseThemeBackgroundColor()
|
||||
)
|
||||
),
|
||||
),
|
||||
BlockView.ButtonOpenFile.FileButton(
|
||||
id = file.id,
|
||||
targetId = currentObjectId
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(expected = expected, actual = result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should render image open block in case of image layout`() {
|
||||
|
||||
val currentObjectId = MockDataFactory.randomUuid()
|
||||
|
||||
val file = StubFile(
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
targetObjectId = currentObjectId,
|
||||
state = Block.Content.File.State.DONE
|
||||
)
|
||||
|
||||
val paragraph = StubParagraph()
|
||||
|
||||
val page = StubSmartBlock(id = currentObjectId, children = listOf(paragraph.id, file.id))
|
||||
|
||||
val details = mapOf(
|
||||
page.id to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to currentObjectId,
|
||||
Relations.NAME to "image-name",
|
||||
Relations.LAYOUT to ObjectType.Layout.IMAGE.code.toDouble()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val blocks = listOf(page, paragraph, file)
|
||||
|
||||
val map = blocks.asMap()
|
||||
|
||||
wrapper = BlockViewRenderWrapper(
|
||||
blocks = map,
|
||||
renderer = renderer
|
||||
)
|
||||
|
||||
val result = runBlocking {
|
||||
wrapper.render(
|
||||
root = page,
|
||||
anchor = page.id,
|
||||
focus = Editor.Focus.empty(),
|
||||
indent = 0,
|
||||
details = Block.Details(details)
|
||||
)
|
||||
}
|
||||
|
||||
val expected = listOf(
|
||||
BlockView.Text.Paragraph(
|
||||
indent = 0,
|
||||
isFocused = false,
|
||||
id = paragraph.id,
|
||||
marks = emptyList(),
|
||||
background = paragraph.parseThemeBackgroundColor(),
|
||||
text = paragraph.content<Block.Content.Text>().text,
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
style = BlockView.Decoration.Style.None,
|
||||
background = paragraph.parseThemeBackgroundColor()
|
||||
)
|
||||
),
|
||||
),
|
||||
BlockView.ButtonOpenFile.ImageButton(
|
||||
id = file.id,
|
||||
targetId = currentObjectId
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.anytypeio.anytype.presentation.editor
|
||||
|
||||
|
||||
import android.R
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
|
@ -9,11 +10,15 @@ import com.anytypeio.anytype.core_models.Block
|
|||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.NetworkModeConfig
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeIds
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.StubNumbered
|
||||
import com.anytypeio.anytype.core_models.StubObject
|
||||
import com.anytypeio.anytype.core_models.StubParagraph
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.ext.content
|
||||
|
@ -2554,70 +2559,26 @@ open class EditorViewModelTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should start sharing a file`() {
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
val file = MockBlockFactory.makeFileBlock()
|
||||
val title = MockBlockFactory.makeTitleBlock()
|
||||
|
||||
val page = listOf(
|
||||
Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart,
|
||||
children = listOf(title.id, file.id)
|
||||
),
|
||||
title,
|
||||
file
|
||||
)
|
||||
|
||||
val flow: Flow<List<Event.Command>> = flow {
|
||||
delay(100)
|
||||
emit(
|
||||
listOf(
|
||||
Event.Command.ShowObject(
|
||||
root = root,
|
||||
blocks = page,
|
||||
context = root
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
stubObserveEvents(flow)
|
||||
stubOpenPage()
|
||||
givenViewModel(builder)
|
||||
|
||||
givenSharedFile()
|
||||
|
||||
vm.onStart(id = root, space = defaultSpace)
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
|
||||
// TESTING
|
||||
|
||||
vm.startSharingFile(id = file.id)
|
||||
|
||||
runTest {
|
||||
verify(documentFileShareDownloader, times(1)).async(
|
||||
params = eq(
|
||||
MiddlewareShareDownloader.Params(
|
||||
name = file.content<Block.Content.File>().name.orEmpty(),
|
||||
objectId = file.content<Block.Content.File>().targetObjectId.orEmpty(),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should start downloading file`() {
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
val file = MockBlockFactory.makeFileBlock()
|
||||
val targetObjectId = MockDataFactory.randomUuid()
|
||||
val file = StubFile(
|
||||
targetObjectId = targetObjectId,
|
||||
type = Block.Content.File.Type.FILE
|
||||
)
|
||||
val title = MockBlockFactory.makeTitleBlock()
|
||||
|
||||
val targetObject = StubObject(
|
||||
id = targetObjectId,
|
||||
name = "file1",
|
||||
layout = ObjectType.Layout.FILE.code.toDouble(),
|
||||
fileExt = ".pdf"
|
||||
)
|
||||
|
||||
val objectDetails = Block.Fields(targetObject.map)
|
||||
|
||||
val page = listOf(
|
||||
Block(
|
||||
id = root,
|
||||
|
@ -2636,12 +2597,19 @@ open class EditorViewModelTest {
|
|||
Event.Command.ShowObject(
|
||||
root = root,
|
||||
blocks = page,
|
||||
context = root
|
||||
context = root,
|
||||
details = Block.Details(mapOf(
|
||||
targetObjectId to objectDetails
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fieldParser.stub {
|
||||
on { getObjectName(targetObject) } doReturn targetObject.name!!
|
||||
}
|
||||
|
||||
stubObserveEvents(flow)
|
||||
stubOpenPage()
|
||||
givenViewModel(builder)
|
||||
|
@ -2654,16 +2622,14 @@ open class EditorViewModelTest {
|
|||
|
||||
// TESTING
|
||||
|
||||
vm.startDownloadingFileFromBlock(blockId = file.id)
|
||||
vm.startDownloadingFileFromBlock(id = file.id)
|
||||
|
||||
runBlockingTest {
|
||||
verify(downloadFile, times(1)).invoke(
|
||||
params = eq(
|
||||
DownloadFile.Params(
|
||||
name = file.content<Block.Content.File>().name.orEmpty(),
|
||||
url = builder.file(
|
||||
path = file.content<Block.Content.File>().targetObjectId!!
|
||||
)
|
||||
name = targetObject.name!!,
|
||||
url = builder.file(path = targetObjectId)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -3423,17 +3389,11 @@ open class EditorViewModelTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `open select picture - when error in edit mode`() {
|
||||
fun `open select picture - when error in edit mode`() = runTest {
|
||||
|
||||
val picture = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
state = Block.Content.File.State.ERROR
|
||||
),
|
||||
children = emptyList()
|
||||
val picture = StubFile(
|
||||
state = Block.Content.File.State.ERROR,
|
||||
type = Block.Content.File.Type.IMAGE
|
||||
)
|
||||
|
||||
val page = listOf(
|
||||
|
@ -3457,10 +3417,10 @@ open class EditorViewModelTest {
|
|||
)
|
||||
|
||||
givenViewModel()
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
vm.onStart(id = root, space = defaultSpace)
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
val expected = listOf(
|
||||
BlockView.Title.Basic(
|
||||
|
@ -3477,7 +3437,8 @@ open class EditorViewModelTest {
|
|||
background = ThemeColor.DEFAULT,
|
||||
style = BlockView.Decoration.Style.Card
|
||||
)
|
||||
)
|
||||
),
|
||||
name = picture.content.asFile().name
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -3500,15 +3461,9 @@ open class EditorViewModelTest {
|
|||
@Test
|
||||
fun `open select video - when error in edit mode`() {
|
||||
|
||||
val video = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
type = Block.Content.File.Type.VIDEO,
|
||||
state = Block.Content.File.State.ERROR
|
||||
),
|
||||
children = emptyList()
|
||||
val video = StubFile(
|
||||
state = Block.Content.File.State.ERROR,
|
||||
type = Block.Content.File.Type.VIDEO
|
||||
)
|
||||
|
||||
val page = listOf(
|
||||
|
@ -3552,7 +3507,8 @@ open class EditorViewModelTest {
|
|||
background = ThemeColor.DEFAULT,
|
||||
style = BlockView.Decoration.Style.Card
|
||||
)
|
||||
)
|
||||
),
|
||||
name = video.content.asFile().name
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -2,6 +2,10 @@ package com.anytypeio.anytype.presentation.editor.editor
|
|||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.StubObject
|
||||
import com.anytypeio.anytype.domain.base.Either
|
||||
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
|
@ -38,15 +42,26 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
|
|||
|
||||
val consumed = mutableListOf<String>()
|
||||
|
||||
val file = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
content = Block.Content.File(
|
||||
targetObjectId = MockDataFactory.randomUuid(),
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.DONE
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList()
|
||||
val fileObjectId = MockDataFactory.randomUuid()
|
||||
|
||||
val fileBlock = StubFile(
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.DONE,
|
||||
targetObjectId = fileObjectId
|
||||
)
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
fileObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to fileObjectId,
|
||||
Relations.NAME to "file object",
|
||||
Relations.SIZE_IN_BYTES to 10000.0,
|
||||
Relations.FILE_MIME_TYPE to "pdf",
|
||||
Relations.LAYOUT to ObjectType.Layout.FILE.code.toDouble()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val doc = listOf(
|
||||
|
@ -54,17 +69,19 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
|
|||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart,
|
||||
children = listOf(file.id)
|
||||
children = listOf(fileBlock.id)
|
||||
),
|
||||
file
|
||||
fileBlock
|
||||
)
|
||||
|
||||
stubOpenDocument(doc)
|
||||
stubOpenDocument(doc, details)
|
||||
stubInterceptEvents()
|
||||
stubDownloadFile()
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
vm.onStart(id = root, space = defaultSpace)
|
||||
|
||||
advanceUntilIdle()
|
||||
|
@ -73,7 +90,7 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
|
|||
|
||||
// Launching operation that triggers a toast
|
||||
|
||||
vm.startDownloadingFileFromBlock(blockId = file.id)
|
||||
vm.startDownloadingFileFromBlock(id = fileBlock.id)
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.anytypeio.anytype.presentation.editor.editor
|
||||
|
||||
import android.R
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.StubBookmark
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.StubTitle
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.ext.content
|
||||
|
@ -28,8 +28,6 @@ import org.junit.Before
|
|||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
class EditorLockPageTest : EditorPresentationTestSetup() {
|
||||
|
@ -585,15 +583,11 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
val fileBlockId = MockDataFactory.randomUuid()
|
||||
val targetObjectId = MockDataFactory.randomUuid()
|
||||
|
||||
val file = Block(
|
||||
val file = StubFile(
|
||||
id = fileBlockId,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
targetObjectId = targetObjectId,
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.DONE
|
||||
),
|
||||
children = emptyList()
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.DONE,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val page = listOf(
|
||||
|
@ -680,8 +674,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
|
||||
testObserver.assertValue { value ->
|
||||
value is EventWrapper && value.peekContent() == Command.OpenFileByDefaultApp(
|
||||
id = fileBlockId,
|
||||
uri = builder.file(targetObjectId)
|
||||
id = fileBlockId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -697,15 +690,10 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
val fileName = "image.png"
|
||||
val fileSize = 1000.0
|
||||
|
||||
val picture = Block(
|
||||
id = fileBlockId,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
targetObjectId = targetObjectId,
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
state = Block.Content.File.State.DONE
|
||||
),
|
||||
children = emptyList()
|
||||
val picture = StubFile(
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
state = Block.Content.File.State.DONE,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val page = listOf(
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.anytypeio.anytype.presentation.editor.editor
|
|||
import android.os.Build
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.StubHeader
|
||||
import com.anytypeio.anytype.core_models.StubLayoutColumns
|
||||
import com.anytypeio.anytype.core_models.StubLayoutRows
|
||||
|
@ -1081,14 +1082,11 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() {
|
|||
)
|
||||
|
||||
val backgroundC = null
|
||||
val c = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.File(
|
||||
state = Block.Content.File.State.EMPTY
|
||||
),
|
||||
backgroundColor = backgroundC
|
||||
|
||||
|
||||
val c = StubFile(
|
||||
backgroundColor = backgroundC,
|
||||
state = Block.Content.File.State.EMPTY
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.presentation.editor.editor.styling
|
|||
|
||||
import android.os.Build
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.TextStyle
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
|
@ -140,12 +141,9 @@ class StyleToolbarExtKtTest {
|
|||
children = emptyList()
|
||||
)
|
||||
|
||||
val given2 = Block(
|
||||
val given2 = StubFile(
|
||||
id = child,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(),
|
||||
backgroundColor = backgroundTeal,
|
||||
children = emptyList()
|
||||
backgroundColor = backgroundTeal
|
||||
)
|
||||
|
||||
val given3 = Block(
|
||||
|
@ -373,12 +371,9 @@ class StyleToolbarExtKtTest {
|
|||
children = emptyList()
|
||||
)
|
||||
|
||||
val given3 = Block(
|
||||
val given3 = StubFile(
|
||||
id = child,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(),
|
||||
backgroundColor = ThemeColor.LIME.code,
|
||||
children = emptyList()
|
||||
backgroundColor = ThemeColor.LIME.code
|
||||
)
|
||||
|
||||
val result =
|
||||
|
|
|
@ -55,6 +55,7 @@ class TableBlockRendererTest {
|
|||
indent: Int,
|
||||
details: Block.Details
|
||||
): List<BlockView> = blocks.render(
|
||||
context = root.id,
|
||||
root = root,
|
||||
anchor = anchor,
|
||||
focus = focus,
|
||||
|
|
|
@ -2,11 +2,20 @@ package com.anytypeio.anytype.presentation.mapper
|
|||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.StubObject
|
||||
import com.anytypeio.anytype.domain.config.Gateway
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParser
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParserImpl
|
||||
import com.anytypeio.anytype.domain.resources.StringResourceProvider
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import org.junit.Before
|
||||
|
@ -23,10 +32,26 @@ class MapperExtensionKtTest {
|
|||
private val urlBuilder: UrlBuilder get() = UrlBuilder(gateway)
|
||||
|
||||
private val targetObjectId : Id = "647tyhfgehf7ru"
|
||||
private val objectId : Id = MockDataFactory.randomUuid()
|
||||
|
||||
lateinit var fieldParser: FieldParser
|
||||
|
||||
@Mock
|
||||
lateinit var dateProvider: DateProvider
|
||||
|
||||
@Mock
|
||||
lateinit var logger: Logger
|
||||
|
||||
@Mock
|
||||
lateinit var getDateObjectByTimestamp: GetDateObjectByTimestamp
|
||||
|
||||
@Mock
|
||||
lateinit var stringResourceProvider: StringResourceProvider
|
||||
|
||||
@Before
|
||||
fun before() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
fieldParser = FieldParserImpl(dateProvider, logger, getDateObjectByTimestamp, stringResourceProvider)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -44,25 +69,28 @@ class MapperExtensionKtTest {
|
|||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
objectId to Block.Fields(
|
||||
StubObject(
|
||||
layout = ObjectType.Layout.BASIC.code.toDouble()
|
||||
).map
|
||||
),
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to targetObjectId,
|
||||
Relations.NAME to name,
|
||||
Relations.SIZE_IN_BYTES to 10000.0,
|
||||
Relations.FILE_MIME_TYPE to mime,
|
||||
Relations.LAYOUT to ObjectType.Layout.FILE.code.toDouble()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = name,
|
||||
size = 10000L,
|
||||
mime = mime,
|
||||
targetObjectId = targetObjectId,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Media.File(
|
||||
id = id,
|
||||
|
@ -75,7 +103,7 @@ class MapperExtensionKtTest {
|
|||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details)
|
||||
val actual = block.toFileView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details, fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -91,15 +119,15 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.FILE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected =
|
||||
BlockView.MediaPlaceholder.File(id = id, indent = indent, isPreviousBlockMedia = false)
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toFileView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -107,6 +135,8 @@ class MapperExtensionKtTest {
|
|||
@Test
|
||||
fun `should return error file block view`() {
|
||||
|
||||
val rootBlockId = MockDataFactory.randomUuid()
|
||||
|
||||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
val indent = MockDataFactory.randomInt()
|
||||
|
@ -115,14 +145,14 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.FILE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Error.File(id = id, indent = indent, decorations = emptyList())
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val expected = BlockView.Error.File(id = id, indent = indent, decorations = emptyList(), name = block.name)
|
||||
val actual = block.toFileView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -138,14 +168,14 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.FILE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Upload.File(id = id, indent = indent)
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toFileView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -165,17 +195,17 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.IMAGE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = targetObjectId,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
).content as Block.Content.File
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to targetObjectId,
|
||||
Relations.NAME to name,
|
||||
Relations.SIZE_IN_BYTES to size,
|
||||
Relations.FILE_MIME_TYPE to mime,
|
||||
|
@ -195,7 +225,7 @@ class MapperExtensionKtTest {
|
|||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details)
|
||||
val actual = block.toPictureView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details, fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -211,18 +241,18 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.IMAGE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.MediaPlaceholder.Picture(
|
||||
id = id,
|
||||
indent = indent,
|
||||
isPreviousBlockMedia = false
|
||||
)
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toPictureView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -238,19 +268,20 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.IMAGE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Error.Picture(
|
||||
id = id,
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
decorations = emptyList(),
|
||||
name = block.name
|
||||
)
|
||||
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toPictureView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -266,14 +297,14 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.IMAGE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Upload.Picture(id = id, indent = indent)
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toPictureView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -293,16 +324,17 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.VIDEO
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = targetObjectId,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
).content as Block.Content.File
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to targetObjectId,
|
||||
Relations.NAME to name,
|
||||
Relations.SIZE_IN_BYTES to 10000.0,
|
||||
Relations.FILE_MIME_TYPE to mime,
|
||||
|
@ -322,7 +354,7 @@ class MapperExtensionKtTest {
|
|||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details)
|
||||
val actual = block.toVideoView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details, fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -338,11 +370,11 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.VIDEO
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = null,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Error.Video(
|
||||
id = id,
|
||||
|
@ -350,7 +382,7 @@ class MapperExtensionKtTest {
|
|||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toVideoView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -366,11 +398,11 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.IMAGE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = null,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = ""
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Error.Picture(
|
||||
id = id,
|
||||
|
@ -378,7 +410,7 @@ class MapperExtensionKtTest {
|
|||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toPictureView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -394,11 +426,11 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.FILE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = null,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = ""
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Error.File(
|
||||
id = id,
|
||||
|
@ -406,7 +438,7 @@ class MapperExtensionKtTest {
|
|||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toFileView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -422,11 +454,11 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.PDF
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = null,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = ""
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Error.File(
|
||||
id = id,
|
||||
|
@ -434,7 +466,7 @@ class MapperExtensionKtTest {
|
|||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toFileView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -450,14 +482,11 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.VIDEO
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
targetObjectId = null,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = ""
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.MediaPlaceholder.Video(
|
||||
id = id,
|
||||
|
@ -465,7 +494,7 @@ class MapperExtensionKtTest {
|
|||
isPreviousBlockMedia = false
|
||||
)
|
||||
|
||||
val actual = block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toVideoView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -481,21 +510,18 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.VIDEO
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
targetObjectId = null,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = ""
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Upload.Video(
|
||||
id = id,
|
||||
indent = indent
|
||||
)
|
||||
|
||||
val actual = block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toVideoView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -511,48 +537,24 @@ class MapperExtensionKtTest {
|
|||
val type = Block.Content.File.Type.VIDEO
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
targetObjectId = null,
|
||||
val block = StubFile(
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
type = type,
|
||||
targetObjectId = ""
|
||||
).content as Block.Content.File
|
||||
|
||||
val expected = BlockView.Error.Video(
|
||||
id = id,
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
decorations = emptyList(),
|
||||
name = block.name
|
||||
)
|
||||
|
||||
val actual = block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toVideoView(objectId, id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), Block.Details(), fieldParser)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun `should throw exceptions when state not set`() {
|
||||
|
||||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
val indent = MockDataFactory.randomInt()
|
||||
|
||||
val type = Block.Content.File.Type.VIDEO
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
targetObjectId = null,
|
||||
state = null,
|
||||
type = type
|
||||
)
|
||||
|
||||
block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not return mark when range from is equal text length`() {
|
||||
// SETUP
|
||||
|
|
|
@ -94,9 +94,11 @@ fun StubFile(
|
|||
backgroundColor: String? = null,
|
||||
targetObjectId: Id = MockDataFactory.randomString(),
|
||||
name: String = MockDataFactory.randomString(),
|
||||
mime: String = MockDataFactory.randomString(),
|
||||
size: Long = MockDataFactory.randomLong(),
|
||||
type: Block.Content.File.Type? = null,
|
||||
state: Block.Content.File.State? = null,
|
||||
type: Block.Content.File.Type = Block.Content.File.Type.FILE,
|
||||
state: Block.Content.File.State = Block.Content.File.State.DONE,
|
||||
addedAt: Long = MockDataFactory.randomLong()
|
||||
) : Block = Block(
|
||||
id = id,
|
||||
children = children,
|
||||
|
@ -107,7 +109,9 @@ fun StubFile(
|
|||
name = name,
|
||||
targetObjectId = targetObjectId,
|
||||
type = type,
|
||||
state = state
|
||||
state = state,
|
||||
mime = mime,
|
||||
addedAt = addedAt
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ fun StubObject(
|
|||
isHidden: Boolean? = null,
|
||||
links: List<Id> = emptyList(),
|
||||
targetObjectType: Id? = null,
|
||||
identity: Id? = null
|
||||
identity: Id? = null,
|
||||
fileExt: String? = null,
|
||||
): ObjectWrapper.Basic = ObjectWrapper.Basic(
|
||||
map = mapOf(
|
||||
Relations.ID to id,
|
||||
|
@ -40,7 +41,8 @@ fun StubObject(
|
|||
Relations.LINKS to links,
|
||||
Relations.TARGET_OBJECT_TYPE to targetObjectType,
|
||||
Relations.UNIQUE_KEY to uniqueKey,
|
||||
Relations.IDENTITY to identity
|
||||
Relations.IDENTITY to identity,
|
||||
Relations.FILE_EXT to fileExt
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -84,20 +84,6 @@ object MockBlockFactory {
|
|||
)
|
||||
)
|
||||
|
||||
fun makeFileBlock(): Block = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
targetObjectId = MockDataFactory.randomUuid(),
|
||||
name = MockDataFactory.randomString(),
|
||||
state = Block.Content.File.State.DONE,
|
||||
mime = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
type = Block.Content.File.Type.FILE
|
||||
),
|
||||
children = emptyList()
|
||||
)
|
||||
|
||||
fun makeTitleBlock(): Block = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue