mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROD-2135 Files as object (#819)
This commit is contained in:
parent
d4d1b3ea3e
commit
a19d1bd8f7
86 changed files with 1256 additions and 1073 deletions
|
@ -134,6 +134,9 @@ EditDataViewViewerFragment : BaseBottomSheetFragment<FragmentEditDataViewViewerB
|
|||
EditDataViewViewerViewModel.ViewState.Calendar -> {
|
||||
toast("TODO")
|
||||
}
|
||||
EditDataViewViewerViewModel.ViewState.Graph -> {
|
||||
toast("TODO")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ data class Block(
|
|||
|
||||
/**
|
||||
* File block.
|
||||
* @property hash file hash
|
||||
* @property targetObjectId id of the target object
|
||||
* @property name filename
|
||||
* @property mime mime type
|
||||
* @property size file size (in bytes)
|
||||
|
@ -226,7 +226,7 @@ data class Block(
|
|||
* @property state file state
|
||||
*/
|
||||
data class File(
|
||||
val hash: String? = null,
|
||||
val targetObjectId: Id? = null,
|
||||
val name: String? = null,
|
||||
val mime: String? = null,
|
||||
val size: Long? = null,
|
||||
|
@ -297,7 +297,8 @@ data class Block(
|
|||
LIST("List"),
|
||||
GALLERY("Gallery"),
|
||||
BOARD("Board"),
|
||||
CALENDAR("Calendar")
|
||||
CALENDAR("Calendar"),
|
||||
GRAPH("Graph")
|
||||
}
|
||||
|
||||
enum class Size { SMALL, MEDIUM, LARGE }
|
||||
|
|
|
@ -27,7 +27,7 @@ sealed class Command {
|
|||
|
||||
class DownloadFile(
|
||||
val path: String,
|
||||
val hash: Hash
|
||||
val objectId: Id
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -177,11 +177,11 @@ sealed class Event {
|
|||
*/
|
||||
data class UpdateFileBlock(
|
||||
override val context: String,
|
||||
val id: Id,
|
||||
val blockId: Id,
|
||||
val targetObjectId: Id? = null,
|
||||
val state: Block.Content.File.State? = null,
|
||||
val type: Block.Content.File.Type? = null,
|
||||
val name: String? = null,
|
||||
val hash: String? = null,
|
||||
val mime: String? = null,
|
||||
val size: Long? = null
|
||||
) : Command()
|
||||
|
|
|
@ -296,4 +296,17 @@ sealed class ObjectWrapper {
|
|||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
data class File(override val map: Struct) : ObjectWrapper() {
|
||||
private val default = map.withDefault { null }
|
||||
val id: Id by default
|
||||
val name: String? by default
|
||||
val description: String? by default
|
||||
val fileExt: String? by default
|
||||
val fileMimeType: String? by default
|
||||
val sizeInBytes: Double? by default
|
||||
val url: String? by default
|
||||
val isArchived: Boolean? by default
|
||||
val isDeleted: Boolean? by default
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ sealed class Response {
|
|||
|
||||
sealed class Media : Response() {
|
||||
class Upload(
|
||||
val hash: String
|
||||
val objectId: Id
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockBookmarkBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockBookmarkErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockBookmarkUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockBulletedBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockCalloutBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockCheckboxBinding
|
||||
|
@ -29,13 +27,12 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockDividerDotsBinding
|
|||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDividerLineBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockFeaturedRelationsBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockFileBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockFileErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockFileUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockHeaderOneBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockHeaderThreeBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockHeaderTwoBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockHighlightBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockLatexBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockNumberedBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkArchiveBinding
|
||||
|
@ -47,8 +44,6 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkCardSmallIco
|
|||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkDeleteBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkLoadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockPictureBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockPictureErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockPictureUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockRelationCheckboxBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockRelationDefaultBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockRelationDeletedBinding
|
||||
|
@ -66,8 +61,6 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockTocBinding
|
|||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockToggleBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockUnsupportedBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockVideoBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockVideoErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockVideoUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Payload
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.dataview.DataViewBlockDefaultHolder
|
||||
|
@ -528,12 +521,12 @@ class BlockAdapter(
|
|||
}
|
||||
HOLDER_FILE_UPLOAD -> {
|
||||
FileUpload(
|
||||
ItemBlockFileUploadingBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaPlaceholderBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_FILE_ERROR -> {
|
||||
FileError(
|
||||
ItemBlockFileErrorBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaErrorBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_VIDEO -> {
|
||||
|
@ -548,12 +541,12 @@ class BlockAdapter(
|
|||
}
|
||||
HOLDER_VIDEO_UPLOAD -> {
|
||||
VideoUpload(
|
||||
ItemBlockVideoUploadingBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaPlaceholderBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_VIDEO_ERROR -> {
|
||||
VideoError(
|
||||
ItemBlockVideoErrorBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaErrorBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_OBJECT_LINK_DEFAULT -> {
|
||||
|
@ -681,12 +674,12 @@ class BlockAdapter(
|
|||
}
|
||||
HOLDER_BOOKMARK_ERROR -> {
|
||||
BookmarkError(
|
||||
ItemBlockBookmarkErrorBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaErrorBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_BOOKMARK_UPLOAD -> {
|
||||
BookmarkUpload(
|
||||
ItemBlockBookmarkUploadingBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaPlaceholderBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_PICTURE -> {
|
||||
|
@ -701,12 +694,12 @@ class BlockAdapter(
|
|||
}
|
||||
HOLDER_PICTURE_UPLOAD -> {
|
||||
PictureUpload(
|
||||
ItemBlockPictureUploadingBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaPlaceholderBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_PICTURE_ERROR -> {
|
||||
PictureError(
|
||||
ItemBlockPictureErrorBinding.inflate(inflater, parent, false)
|
||||
ItemBlockMediaErrorBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_DIVIDER_LINE -> {
|
||||
|
|
|
@ -36,6 +36,19 @@ interface DecoratableCardViewHolder : DecoratableViewHolder {
|
|||
}
|
||||
}
|
||||
|
||||
interface DecoratableMediaErrorViewHolder : DecoratableViewHolder {
|
||||
val decoratableCard: View
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
decoratableContainer.decorate(decorations) { rect ->
|
||||
decoratableCard.applyMediaErrorDecorations<FrameLayout.LayoutParams>(
|
||||
rect = rect,
|
||||
res = decoratableCard.resources
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applying decorations for card blocks (media blocks, placeholders, link-to-objects, bookmarks, etc.)
|
||||
*/
|
||||
|
@ -62,4 +75,18 @@ inline fun <reified LP : ViewGroup.MarginLayoutParams> View.applySelectorOffset(
|
|||
marginEnd = content.marginEnd - selectorLeftRightOffset
|
||||
topMargin = content.marginTop
|
||||
bottomMargin = content.marginBottom
|
||||
}
|
||||
|
||||
/**
|
||||
* Applying decorations for media error blocks
|
||||
*/
|
||||
inline fun <reified LP : ViewGroup.MarginLayoutParams> View.applyMediaErrorDecorations(
|
||||
rect: Rect,
|
||||
res: Resources
|
||||
) = updateLayoutParams<LP> {
|
||||
val defaultIndentOffset = res.getDimension(R.dimen.default_indent).toInt()
|
||||
marginStart = defaultIndentOffset + rect.left
|
||||
marginEnd = defaultIndentOffset + rect.right
|
||||
topMargin = res.getDimension(R.dimen.card_block_extra_space_top).toInt()
|
||||
bottomMargin = res.getDimension(R.dimen.dp_8).toInt() + rect.bottom
|
||||
}
|
|
@ -1,35 +1,14 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.error
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockBookmarkErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class BookmarkError(
|
||||
val binding: ItemBlockBookmarkErrorBinding
|
||||
) : MediaError(binding.root), DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = binding.bookmarkErrorRoot
|
||||
private val urlView: TextView = binding.errorBookmarkUrl
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
override val decoratableCard: View
|
||||
get() = binding.card
|
||||
|
||||
fun setUrl(url: String) {
|
||||
urlView.text = url.ifEmpty { null }
|
||||
}
|
||||
binding: ItemBlockMediaErrorBinding
|
||||
) : MediaError(binding) {
|
||||
|
||||
override fun errorClick(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
if (item is BlockView.Error.Bookmark) {
|
||||
|
@ -37,20 +16,11 @@ class BookmarkError(
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
override fun bind(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_bookmark_inactive))
|
||||
if (item is BlockView.Error.Bookmark) {
|
||||
binding.fileName.text = item.url.ifEmpty { null }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +1,30 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.error
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockFileErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class FileError(
|
||||
val binding: ItemBlockFileErrorBinding
|
||||
) : MediaError(binding.root), DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
override val decoratableCard: View
|
||||
get() = binding.card
|
||||
binding: ItemBlockMediaErrorBinding
|
||||
) : MediaError(binding) {
|
||||
|
||||
override fun errorClick(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
clicked(ListenerType.File.Error(item.id))
|
||||
if (item is BlockView.Error.File) {
|
||||
clicked(ListenerType.File.Error(item.id))
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
override fun bind(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
if (item is BlockView.Error.File) {
|
||||
binding.fileName.text = if (item.name.isNullOrBlank()) {
|
||||
itemView.resources.getString(R.string.hint_upload_file)
|
||||
} else
|
||||
item.name
|
||||
}
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_file_light_inactive))
|
||||
}
|
||||
}
|
|
@ -1,24 +1,31 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.error
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.marginEnd
|
||||
import androidx.core.view.marginStart
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaErrorBinding
|
||||
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.EditorTouchProcessor
|
||||
import com.anytypeio.anytype.core_ui.features.editor.SupportCustomTouchProcessor
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableMediaErrorViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
abstract class MediaError(
|
||||
view: View
|
||||
) : BlockViewHolder(view),
|
||||
val binding: ItemBlockMediaErrorBinding
|
||||
) : BlockViewHolder(binding.root),
|
||||
BlockViewHolder.IndentableHolder,
|
||||
BlockViewHolder.DragAndDropHolder,
|
||||
SupportCustomTouchProcessor {
|
||||
SupportCustomTouchProcessor, DecoratableMediaErrorViewHolder {
|
||||
|
||||
abstract val root: View
|
||||
override val decoratableContainer: EditorDecorationContainer get() = binding.decorationContainer
|
||||
override val decoratableCard: View get() = binding.card
|
||||
val errorIcon: View get() = binding.errorMessage
|
||||
abstract fun errorClick(item: BlockView.Error, clicked: (ListenerType) -> Unit)
|
||||
abstract override fun indentize(item: BlockView.Indentable)
|
||||
abstract fun select(isSelected: Boolean)
|
||||
|
||||
override val editorTouchProcessor = EditorTouchProcessor(
|
||||
fallback = { e -> itemView.onTouchEvent(e) }
|
||||
|
@ -28,23 +35,45 @@ abstract class MediaError(
|
|||
itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
|
||||
}
|
||||
|
||||
fun bind(
|
||||
open fun bind(
|
||||
item: BlockView.Error,
|
||||
clicked: (ListenerType) -> Unit
|
||||
) {
|
||||
indentize(item)
|
||||
select(item.isSelected)
|
||||
with(itemView) {
|
||||
setOnClickListener { errorClick(item, clicked) }
|
||||
}
|
||||
}
|
||||
|
||||
fun processChangePayload(payloads: List<BlockViewDiffUtil.Payload>, item: BlockView) {
|
||||
check(item is BlockView.Error) { "Expected error block, but was: $item" }
|
||||
open fun processChangePayload(payloads: List<BlockViewDiffUtil.Payload>, item: BlockView) {
|
||||
check(item is BlockView.Error) { "Expected error media block, but was: $item" }
|
||||
payloads.forEach { payload ->
|
||||
if (payload.isSelectionChanged) {
|
||||
itemView.isSelected = item.isSelected
|
||||
select(item.isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
val selectorLeftRightOffset = itemView.resources.getDimension(R.dimen.selection_left_right_offset).toInt()
|
||||
marginStart = binding.card.marginStart - selectorLeftRightOffset
|
||||
marginEnd = binding.card.marginEnd - selectorLeftRightOffset
|
||||
topMargin = itemView.resources.getDimension(R.dimen.card_block_extra_space_top).toInt()
|
||||
bottomMargin = 0
|
||||
}
|
||||
errorIcon.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
marginStart = binding.card.marginStart
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
|
@ -1,48 +1,30 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.error
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockPictureErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class PictureError(
|
||||
val binding: ItemBlockPictureErrorBinding
|
||||
) : MediaError(binding.root), DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
override val decoratableCard: View
|
||||
get() = binding.card
|
||||
binding: ItemBlockMediaErrorBinding
|
||||
) : MediaError(binding) {
|
||||
|
||||
override fun errorClick(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
clicked(ListenerType.Picture.Error(item.id))
|
||||
if (item is BlockView.Error.Picture) {
|
||||
clicked(ListenerType.Picture.Error(item.id))
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
override fun bind(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
if (item is BlockView.Error.Picture) {
|
||||
binding.fileName.text = if (item.name.isNullOrBlank()) {
|
||||
itemView.resources.getString(R.string.hint_upload_image)
|
||||
} else
|
||||
item.name
|
||||
}
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_picture_inactive))
|
||||
}
|
||||
}
|
|
@ -1,48 +1,30 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.error
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockVideoErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaErrorBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class VideoError(
|
||||
val binding: ItemBlockVideoErrorBinding
|
||||
) : MediaError(binding.root), DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
override val decoratableCard: View
|
||||
get() = binding.card
|
||||
binding: ItemBlockMediaErrorBinding
|
||||
) : MediaError(binding) {
|
||||
|
||||
override fun errorClick(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
clicked(ListenerType.Video.Error(item.id))
|
||||
if (item is BlockView.Error.Video) {
|
||||
clicked(ListenerType.Video.Error(item.id))
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
override fun bind(item: BlockView.Error, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
if (item is BlockView.Error.Video) {
|
||||
binding.fileName.text = if (item.name.isNullOrBlank()) {
|
||||
itemView.resources.getString(R.string.hint_upload_video)
|
||||
} else
|
||||
item.name
|
||||
}
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_video_inactive))
|
||||
}
|
||||
}
|
|
@ -45,9 +45,22 @@ class File(val binding: ItemBlockFileBinding) : Media(binding.root), Decoratable
|
|||
name.enableReadMode()
|
||||
if (item.size != null && item.name != null) {
|
||||
val size = item.size!!.readableFileSize()
|
||||
val spannable = SpannableString("${item.name} $size")
|
||||
val start = item.name!!.length + 2
|
||||
val end = item.name!!.length + 2 + size.length
|
||||
|
||||
val spannable = if (item.fileExt.isNullOrBlank()) {
|
||||
SpannableString("${item.name} $size")
|
||||
} else {
|
||||
SpannableString("${item.name}.${item.fileExt} $size")
|
||||
}
|
||||
val start = if (item.fileExt.isNullOrBlank()) {
|
||||
item.name!!.length + 2
|
||||
} else {
|
||||
item.name!!.length + item.fileExt!!.length + 2
|
||||
}
|
||||
val end = if (item.fileExt.isNullOrBlank()) {
|
||||
item.name!!.length + 2 + size.length
|
||||
} else {
|
||||
item.name!!.length + item.fileExt!!.length + 3 + size.length
|
||||
}
|
||||
spannable.setSpan(
|
||||
RelativeSizeSpan(0.87f),
|
||||
start,
|
||||
|
|
|
@ -2,9 +2,8 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.placeholders
|
|||
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class BookmarkPlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlaceholder(binding) {
|
||||
|
||||
|
@ -14,15 +13,6 @@ class BookmarkPlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlac
|
|||
|
||||
override fun setup() {
|
||||
title.text = itemView.resources.getString(R.string.hint_add_a_web_bookmark)
|
||||
title.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_bookmark_placeholder, 0, 0, 0)
|
||||
}
|
||||
|
||||
override fun processChangePayload(payloads: List<BlockViewDiffUtil.Payload>, item: BlockView) {
|
||||
super.processChangePayload(payloads, item)
|
||||
// TODO process loading state changes
|
||||
}
|
||||
|
||||
fun isLoading(boolean: Boolean) {
|
||||
// TODO process loading state changes
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_bookmark_placeholder))
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.placeholders
|
|||
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
|
||||
class FilePlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlaceholder(binding) {
|
||||
|
@ -12,6 +13,6 @@ class FilePlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlacehol
|
|||
|
||||
override fun setup() {
|
||||
title.text = itemView.resources.getString(R.string.hint_upload_file)
|
||||
title.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_file_light, 0, 0, 0)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_file_light))
|
||||
}
|
||||
}
|
|
@ -3,11 +3,6 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.placeholders
|
|||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.veryLight
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
|
||||
|
@ -17,8 +12,7 @@ import com.anytypeio.anytype.core_ui.features.editor.SupportCustomTouchProcessor
|
|||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_utils.ext.invisible
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
|
@ -33,7 +27,7 @@ abstract class MediaPlaceholder(
|
|||
|
||||
protected val root: View = binding.root
|
||||
protected val card: MaterialCardView = binding.card
|
||||
protected val title: TextView = binding.title
|
||||
protected val title: TextView = binding.fileName
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
|
@ -61,6 +55,7 @@ abstract class MediaPlaceholder(
|
|||
with(itemView) {
|
||||
setOnClickListener { placeholderClick(item.id, clicked) }
|
||||
}
|
||||
binding.progressBar.invisible()
|
||||
}
|
||||
|
||||
open fun processChangePayload(payloads: List<BlockViewDiffUtil.Payload>, item: BlockView) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.placeholders
|
|||
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
|
||||
class PicturePlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlaceholder(binding) {
|
||||
|
@ -12,6 +13,6 @@ class PicturePlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlace
|
|||
|
||||
override fun setup() {
|
||||
title.text = itemView.resources.getString(R.string.hint_upload_image)
|
||||
title.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_picture, 0, 0, 0)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_picture))
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.placeholders
|
|||
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
|
||||
class VideoPlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlaceholder(binding) {
|
||||
|
@ -12,6 +13,6 @@ class VideoPlaceholder(binding: ItemBlockMediaPlaceholderBinding) : MediaPlaceho
|
|||
|
||||
override fun setup() {
|
||||
title.text = itemView.resources.getString(R.string.hint_upload_video)
|
||||
title.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_video, 0, 0, 0)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_video))
|
||||
}
|
||||
}
|
|
@ -1,54 +1,27 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.upload
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockBookmarkUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockFileUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class BookmarkUpload(
|
||||
private val binding: ItemBlockBookmarkUploadingBinding
|
||||
) : MediaUpload(binding.root), DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
|
||||
override val decoratableCard: View = binding.card
|
||||
binding: ItemBlockMediaPlaceholderBinding
|
||||
) : MediaUpload(binding), DecoratableCardViewHolder {
|
||||
|
||||
override fun uploadClick(target: String, clicked: (ListenerType) -> Unit) {
|
||||
clicked(ListenerType.File.Upload(target))
|
||||
clicked(ListenerType.Bookmark.Upload(target))
|
||||
}
|
||||
|
||||
fun setUrl(url: Url?) {
|
||||
binding.editUrl.text = url
|
||||
binding.fileName.text = url
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
override fun bind(item: BlockView.Upload, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_bookmark_inactive))
|
||||
}
|
||||
}
|
|
@ -1,47 +1,22 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.upload
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockFileUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class FileUpload(
|
||||
private val binding: ItemBlockFileUploadingBinding
|
||||
) : MediaUpload(binding.root), DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
|
||||
override val decoratableCard: View = binding.card
|
||||
binding: ItemBlockMediaPlaceholderBinding
|
||||
) : MediaUpload(binding), DecoratableCardViewHolder {
|
||||
|
||||
override fun uploadClick(target: String, clicked: (ListenerType) -> Unit) {
|
||||
clicked(ListenerType.File.Upload(target))
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
override fun bind(item: BlockView.Upload, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_file_light_inactive))
|
||||
}
|
||||
}
|
|
@ -1,29 +1,27 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.upload
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import android.widget.FrameLayout
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
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.EditorTouchProcessor
|
||||
import com.anytypeio.anytype.core_ui.features.editor.SupportCustomTouchProcessor
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
abstract class MediaUpload(
|
||||
view: View
|
||||
) : BlockViewHolder(view),
|
||||
val binding: ItemBlockMediaPlaceholderBinding
|
||||
) : BlockViewHolder(binding.root),
|
||||
BlockViewHolder.IndentableHolder,
|
||||
SupportCustomTouchProcessor {
|
||||
SupportCustomTouchProcessor, DecoratableCardViewHolder {
|
||||
|
||||
abstract val root: View
|
||||
override val decoratableContainer: EditorDecorationContainer get() = binding.decorationContainer
|
||||
override val decoratableCard: View get() = binding.card
|
||||
abstract fun uploadClick(target: String, clicked: (ListenerType) -> Unit)
|
||||
abstract override fun indentize(item: BlockView.Indentable)
|
||||
abstract fun select(isSelected: Boolean)
|
||||
|
||||
override val editorTouchProcessor = EditorTouchProcessor(
|
||||
fallback = { e -> itemView.onTouchEvent(e) }
|
||||
|
@ -33,11 +31,10 @@ abstract class MediaUpload(
|
|||
itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
|
||||
}
|
||||
|
||||
fun bind(
|
||||
open fun bind(
|
||||
item: BlockView.Upload,
|
||||
clicked: (ListenerType) -> Unit
|
||||
) {
|
||||
indentize(item)
|
||||
select(item.isSelected)
|
||||
with(itemView) {
|
||||
setOnClickListener { uploadClick(item.id, clicked) }
|
||||
|
@ -52,4 +49,21 @@ abstract class MediaUpload(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,38 +1,22 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.upload
|
||||
|
||||
import android.view.View
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockPictureUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class PictureUpload(
|
||||
private val binding: ItemBlockPictureUploadingBinding
|
||||
) : MediaUpload(binding.root), DecoratableViewHolder, DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
|
||||
override val decoratableCard: View get() = binding.card
|
||||
binding: ItemBlockMediaPlaceholderBinding
|
||||
) : MediaUpload(binding), DecoratableCardViewHolder {
|
||||
|
||||
override fun uploadClick(target: String, clicked: (ListenerType) -> Unit) {
|
||||
clicked(ListenerType.Video.Upload(target))
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
root.isSelected = isSelected
|
||||
override fun bind(item: BlockView.Upload, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_picture_inactive))
|
||||
}
|
||||
}
|
|
@ -1,47 +1,22 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.upload
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockVideoUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockMediaPlaceholderBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.drawable
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.applySelectorOffset
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.indentize
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class VideoUpload(
|
||||
val binding: ItemBlockVideoUploadingBinding
|
||||
) : MediaUpload(binding.root), DecoratableCardViewHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
get() = binding.decorationContainer
|
||||
|
||||
override val decoratableCard: View = binding.card
|
||||
binding: ItemBlockMediaPlaceholderBinding
|
||||
) : MediaUpload(binding), DecoratableCardViewHolder {
|
||||
|
||||
override fun uploadClick(target: String, clicked: (ListenerType) -> Unit) {
|
||||
clicked(ListenerType.Video.Upload(target))
|
||||
}
|
||||
|
||||
@Deprecated("Pre-nested-styling legacy.")
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
override fun select(isSelected: Boolean) {
|
||||
binding.selected.isSelected = isSelected
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
binding.selected.applySelectorOffset<FrameLayout.LayoutParams>(
|
||||
content = binding.card,
|
||||
res = itemView.resources
|
||||
)
|
||||
override fun bind(item: BlockView.Upload, clicked: (ListenerType) -> Unit) {
|
||||
super.bind(item, clicked)
|
||||
binding.fileIcon.setImageDrawable(itemView.context.drawable(R.drawable.ic_video_inactive))
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
<path
|
||||
android:pathData="M15.627,21.766L8.75,25.706V9C8.75,7.205 10.205,5.75 12,5.75H20C21.795,5.75 23.25,7.205 23.25,9V25.706L16.373,21.766L16,21.552L15.627,21.766Z"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/glyph_inactive"/>
|
||||
</vector>
|
11
core-ui/src/main/res/drawable/ic_bookmark_inactive.xml
Normal file
11
core-ui/src/main/res/drawable/ic_bookmark_inactive.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="25dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="25">
|
||||
<path
|
||||
android:pathData="M11.6272,18.0496L4.75,21.9896V5.2837C4.75,3.4888 6.2051,2.0337 8,2.0337H16C17.7949,2.0337 19.25,3.4888 19.25,5.2837V21.9896L12.3728,18.0496L12,17.836L11.6272,18.0496Z"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/glyph_inactive"/>
|
||||
</vector>
|
27
core-ui/src/main/res/drawable/ic_file_light_inactive.xml
Normal file
27
core-ui/src/main/res/drawable/ic_file_light_inactive.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="25dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="25">
|
||||
<path
|
||||
android:pathData="M12.2487,2.6655L13.2208,3.6377L5.1197,11.7388L4.1476,10.7667L12.2487,2.6655Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M18.7246,9.1415C20.0866,7.6118 20.0341,5.2662 18.5673,3.7994C17.1005,2.3326 14.7549,2.2801 13.2252,3.6421L12.2519,2.6687C14.3196,0.7706 17.5356,0.8235 19.5394,2.8273C21.5432,4.8311 21.5961,8.0471 19.698,10.1148L18.7246,9.1415Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M13.5449,20.164C11.2183,22.4905 7.4463,22.4905 5.1197,20.164C2.7932,17.8374 2.7932,14.0653 5.1197,11.7388L4.1476,10.7667C1.2841,13.6301 1.2841,18.2727 4.1476,21.1361C7.011,23.9996 11.6536,23.9996 14.517,21.1361L13.5449,20.164Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M14.193,6.5541L15.1651,7.5262L8.6842,14.0071L7.7121,13.035L14.193,6.5541Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M11.2766,16.5995C10.5607,17.3153 9.4001,17.3153 8.6842,16.5995C7.9683,15.8836 7.9683,14.723 8.6842,14.0071L7.7121,13.035C6.4593,14.2877 6.4593,16.3189 7.7121,17.5716C8.9648,18.8244 10.996,18.8244 12.2487,17.5716L11.2766,16.5995Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M18.7296,9.1464L19.7017,10.1186L12.2487,17.5716L11.2766,16.5995L18.7296,9.1464Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M20.6739,13.035L21.646,14.0071L14.517,21.1361L13.5449,20.164L20.6739,13.035Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
</vector>
|
17
core-ui/src/main/res/drawable/ic_picture_inactive.xml
Normal file
17
core-ui/src/main/res/drawable/ic_picture_inactive.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="25dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="25">
|
||||
<path
|
||||
android:pathData="M9,2.7837H15C16.4249,2.7837 17.4033,2.7849 18.1618,2.8468C18.9028,2.9074 19.3009,3.0184 19.589,3.1652C20.2475,3.5007 20.783,4.0362 21.1185,4.6947C21.2653,4.9828 21.3763,5.3808 21.4369,6.1219C21.4988,6.8804 21.5,7.8588 21.5,9.2837V15.2837C21.5,16.7086 21.4988,17.687 21.4369,18.4455C21.3763,19.1865 21.2653,19.5846 21.1185,19.8727C20.783,20.5312 20.2475,21.0667 19.589,21.4022C19.3009,21.549 18.9028,21.66 18.1618,21.7206C17.4033,21.7825 16.4249,21.7837 15,21.7837H9C7.5751,21.7837 6.5967,21.7825 5.8382,21.7206C5.0972,21.66 4.6991,21.549 4.411,21.4022C3.7525,21.0667 3.217,20.5312 2.8815,19.8727C2.7347,19.5846 2.6237,19.1865 2.5631,18.4455C2.5012,17.687 2.5,16.7086 2.5,15.2837V9.2837C2.5,7.8588 2.5012,6.8804 2.5631,6.1219C2.6237,5.3808 2.7347,4.9828 2.8815,4.6947C3.217,4.0362 3.7525,3.5007 4.411,3.1652C4.6991,3.0184 5.0972,2.9074 5.8382,2.8468C6.5967,2.7849 7.5751,2.7837 9,2.7837ZM22.455,4.0137C23,5.0833 23,6.4834 23,9.2837V15.2837C23,18.084 23,19.4841 22.455,20.5536C21.9757,21.4945 21.2108,22.2594 20.27,22.7387C19.2004,23.2837 17.8003,23.2837 15,23.2837H9C6.1997,23.2837 4.7996,23.2837 3.7301,22.7387C2.7892,22.2594 2.0243,21.4945 1.545,20.5536C1,19.4841 1,18.084 1,15.2837V9.2837C1,6.4834 1,5.0833 1.545,4.0137C2.0243,3.0729 2.7892,2.308 3.7301,1.8287C4.7996,1.2837 6.1997,1.2837 9,1.2837H15C17.8003,1.2837 19.2004,1.2837 20.27,1.8287C21.2108,2.308 21.9757,3.0729 22.455,4.0137Z"
|
||||
android:fillColor="@color/glyph_inactive"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M8.5,10.2837C7.3954,10.2837 6.5,9.3883 6.5,8.2837C6.5,7.1791 7.3954,6.2837 8.5,6.2837C9.6046,6.2837 10.5,7.1791 10.5,8.2837C10.5,9.3883 9.6046,10.2837 8.5,10.2837Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M14.5015,11.8428C14.5126,11.8539 14.5244,11.8656 14.5368,11.878L21.4712,18.773L22.5288,17.7094L15.5945,10.8143C15.5897,10.8096 15.585,10.8048 15.5802,10.8001C15.4938,10.7141 15.4001,10.6209 15.3124,10.5469C15.2131,10.463 15.0734,10.361 14.8849,10.3002C14.6341,10.2192 14.3642,10.2196 14.1137,10.3013C13.9254,10.3626 13.786,10.4651 13.6869,10.5492C13.5994,10.6235 13.506,10.717 13.4198,10.8031C13.4151,10.8079 13.4103,10.8127 13.4056,10.8174L9.5004,14.7226L8.0817,13.3018C7.9954,13.2153 7.9018,13.1215 7.8142,13.047C7.715,12.9627 7.5753,12.8599 7.3866,12.7985C7.1356,12.7167 6.8652,12.7165 6.6141,12.7979C6.4253,12.8591 6.2854,12.9616 6.1861,13.0458C6.0984,13.1202 6.0047,13.2138 5.9183,13.3001L1.47,17.7417L2.5299,18.8031L6.9638,14.3759C6.9763,14.3634 6.988,14.3517 6.9992,14.3406C7.0103,14.3517 7.0221,14.3635 7.0345,14.3759L9.4996,16.8447L14.4662,11.8781C14.4787,11.8656 14.4904,11.8539 14.5015,11.8428Z"
|
||||
android:fillColor="@color/glyph_inactive"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
18
core-ui/src/main/res/drawable/ic_video_inactive.xml
Normal file
18
core-ui/src/main/res/drawable/ic_video_inactive.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="25dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="25">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0.2837h24v24h-24z"/>
|
||||
<path
|
||||
android:pathData="M12,1.0337L12,1.0337A11.25,11.25 0,0 1,23.25 12.2837L23.25,12.2837A11.25,11.25 0,0 1,12 23.5337L12,23.5337A11.25,11.25 0,0 1,0.75 12.2837L0.75,12.2837A11.25,11.25 0,0 1,12 1.0337z"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/glyph_inactive"/>
|
||||
<path
|
||||
android:pathData="M17.7526,12.7162C18.0852,12.5236 18.0852,12.0434 17.7526,11.8508L9.7505,7.2182C9.4172,7.0252 9,7.2657 9,7.6509V16.9165C9,17.3016 9.4172,17.5422 9.7505,17.3492L17.7526,12.7162Z"
|
||||
android:fillColor="@color/glyph_inactive"/>
|
||||
</group>
|
||||
</vector>
|
|
@ -1,68 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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/fileUploadingPlaceholderRoot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_48"
|
||||
android:background="@drawable/rectangle_media_block_placeholder">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivBookmark"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/content_description_bookmark_image"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_bookmark_block_loading" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editUrl"
|
||||
style="@style/TextView.ContentStyle.Relations.3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:inputType="none"
|
||||
android:hint="@string/loading_wait"
|
||||
android:textColor="@color/glyph_inactive"
|
||||
android:textColorHint="@color/glyph_inactive"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/ivBookmark"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivBookmark"
|
||||
app:layout_constraintTop_toTopOf="@+id/ivBookmark" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:indeterminateTint="@color/glyph_inactive"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/editUrl"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/editUrl" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/selected"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
tools:background="@drawable/item_block_multi_select_selected" />
|
||||
|
||||
</FrameLayout>
|
|
@ -18,6 +18,8 @@
|
|||
android:paddingEnd="@dimen/default_document_content_padding_start"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/dp_4"
|
||||
android:paddingBottom="@dimen/dp_4"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
tools:background="@drawable/item_block_multi_select_selected">
|
||||
|
||||
|
@ -30,17 +32,25 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/graphic"
|
||||
style="@style/DefaultGraphicTextBlockGraphicStyle"
|
||||
android:layout_width="@dimen/dp_24"
|
||||
android:layout_height="@dimen/dp_24"
|
||||
android:contentDescription="@string/content_description_file_icon"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@drawable/ic_mime_image" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
android:id="@+id/text"
|
||||
style="@style/DefaultGraphicTextBlockTextStyle"
|
||||
style="@style/TextView.ContentStyle.Body.Regular"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:ellipsize="middle"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:background="@null"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/graphic"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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/fileUploadingPlaceholderRoot"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_48"
|
||||
android:background="@drawable/rectangle_media_block_placeholder">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icFile"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/content_description_file_icon"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_file_light" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editUrl"
|
||||
style="@style/UploadMediaInActiveTextStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/loading_wait"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/icFile"
|
||||
app:layout_constraintStart_toEndOf="@+id/icFile"
|
||||
app:layout_constraintTop_toTopOf="@+id/icFile" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icMore"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_block_more" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:indeterminateTint="@color/glyph_inactive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/editUrl"
|
||||
app:layout_constraintStart_toEndOf="@+id/editUrl"
|
||||
app:layout_constraintTop_toTopOf="@+id/editUrl" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/selected"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
tools:background="@drawable/item_block_multi_select_selected" />
|
||||
</FrameLayout>
|
87
core-ui/src/main/res/layout/item_block_media_error.xml
Normal file
87
core-ui/src/main/res/layout/item_block_media_error.xml
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card"
|
||||
style="@style/DefaultMediaPlaceholderBlockCardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fileIcon"
|
||||
android:layout_width="@dimen/dp_32"
|
||||
android:layout_height="@dimen/dp_32"
|
||||
android:scaleType="center"
|
||||
android:layout_marginStart="@dimen/dp_12"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_picture" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileName"
|
||||
style="@style/TextView.ContentStyle.Body.Callout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:drawablePadding="@dimen/default_media_placeholder_title_icon_padding"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:text="@string/loading_please_wait"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/progressBar"
|
||||
app:layout_constraintStart_toEndOf="@+id/fileIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="https://github.com/anyproto/anytype-kotlin"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/try_again"
|
||||
style="@style/TextView.UXStyle.Captions.1.Medium"
|
||||
android:textColor="@color/text_primary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginEnd="@dimen/dp_12"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errorMessage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="66dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:textColor="@color/palette_system_red"
|
||||
style="@style/TextView.UXStyle.Captions.2.Regular"
|
||||
android:text="@string/block_media_error"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/selected"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
tools:background="@drawable/item_block_multi_select_selected" />
|
||||
</FrameLayout>
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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"
|
||||
|
@ -14,22 +15,59 @@
|
|||
android:id="@+id/card"
|
||||
style="@style/DefaultMediaPlaceholderBlockCardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="52dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextView.ContentStyle.Body.Callout"
|
||||
android:textColor="@color/glyph_active"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/default_media_placeholder_title_margin_start"
|
||||
android:layout_marginTop="14dp"
|
||||
android:layout_marginBottom="14dp"
|
||||
android:drawablePadding="@dimen/default_media_placeholder_title_icon_padding"
|
||||
android:gravity="center_vertical"
|
||||
tools:drawableStart="@drawable/ic_picture"
|
||||
tools:text="Add a web bookmark" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fileIcon"
|
||||
android:layout_width="@dimen/dp_32"
|
||||
android:layout_height="@dimen/dp_32"
|
||||
android:scaleType="center"
|
||||
android:layout_marginStart="@dimen/dp_12"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_picture" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileName"
|
||||
style="@style/TextView.ContentStyle.Body.Callout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:drawablePadding="@dimen/default_media_placeholder_title_icon_padding"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:text="@string/loading_please_wait"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/progressBar"
|
||||
app:layout_constraintStart_toEndOf="@+id/fileIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="https://github.com/anyproto/anytype-kotlin"/>
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:trackColor="@color/glyph_inactive"
|
||||
app:indicatorColor="#B6B6B6"
|
||||
app:indicatorSize="20dp"
|
||||
app:trackThickness="@dimen/dp_2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginEnd="@dimen/dp_12"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<View
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
style="@style/BlockMediaRootLayoutStyle"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_48"
|
||||
android:background="@drawable/rectangle_media_block_placeholder">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icPicture"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/content_description_file_icon"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_file_light" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editUrl"
|
||||
style="@style/UploadMediaTextStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:inputType="none"
|
||||
android:text="@string/loading_wait"
|
||||
android:textColor="@color/glyph_active"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/icPicture"
|
||||
app:layout_constraintStart_toEndOf="@+id/icPicture"
|
||||
app:layout_constraintTop_toTopOf="@+id/icPicture" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:indeterminateTint="@color/glyph_inactive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/editUrl"
|
||||
app:layout_constraintStart_toEndOf="@+id/editUrl"
|
||||
app:layout_constraintTop_toTopOf="@+id/editUrl" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
|
@ -1,63 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/videoUploadingPlaceholderRoot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_48"
|
||||
android:background="@drawable/rectangle_media_block_placeholder">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icVideo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/content_description_file_icon"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_video" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editUrl"
|
||||
style="@style/UploadMediaInActiveTextStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/loading_wait"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/icVideo"
|
||||
app:layout_constraintStart_toEndOf="@+id/icVideo"
|
||||
app:layout_constraintTop_toTopOf="@+id/icVideo" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:indeterminateTint="@color/glyph_inactive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/editUrl"
|
||||
app:layout_constraintStart_toEndOf="@+id/editUrl"
|
||||
app:layout_constraintTop_toTopOf="@+id/editUrl" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/selected"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector" />
|
||||
|
||||
</FrameLayout>
|
|
@ -652,16 +652,6 @@
|
|||
<item name="android:layout_marginTop">@dimen/default_graphic_text_graphic_margin_top</item>
|
||||
</style>
|
||||
|
||||
<!-- text -->
|
||||
<style name="DefaultGraphicTextBlockTextStyle" parent="TextView.ContentStyle.Body.Regular">
|
||||
<item name="android:layout_width">@dimen/default_graphic_text_graphic_width</item>
|
||||
<item name="android:layout_height">@dimen/default_graphic_text_graphic_width</item>
|
||||
<item name="android:layout_marginStart">@dimen/default_graphic_text_text_margin_start</item>
|
||||
<item name="android:paddingTop">@dimen/default_graphic_text_text_padding_top</item>
|
||||
<item name="android:paddingBottom">@dimen/default_graphic_text_text_padding_bottom</item>
|
||||
<item name="android:background">@null</item>
|
||||
</style>
|
||||
|
||||
<!-- Media placeholder {root {card {title}} selected}-->
|
||||
<!-- root -->
|
||||
<style name="DefaultMediaPlaceholderBlockRootStyle">
|
||||
|
|
|
@ -2281,7 +2281,7 @@ class BlockAdapterTest {
|
|||
val views = listOf(
|
||||
BlockView.Media.File(
|
||||
id = MockDataFactory.randomString(),
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
indent = MockDataFactory.randomInt(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
|
@ -2292,7 +2292,7 @@ class BlockAdapterTest {
|
|||
),
|
||||
BlockView.Media.File(
|
||||
id = MockDataFactory.randomString(),
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
indent = MockDataFactory.randomInt(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
|
@ -2330,7 +2330,7 @@ class BlockAdapterTest {
|
|||
|
||||
val file = BlockView.Media.File(
|
||||
id = MockDataFactory.randomString(),
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
indent = MockDataFactory.randomInt(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
|
@ -2594,7 +2594,7 @@ class BlockAdapterTest {
|
|||
|
||||
private fun givenPicture() = BlockView.Media.Picture(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
indent = MockDataFactory.randomInt(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
name = MockDataFactory.randomString(),
|
||||
|
@ -2606,7 +2606,7 @@ class BlockAdapterTest {
|
|||
private fun givenVideo() = BlockView.Media.Video(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
indent = MockDataFactory.randomInt(),
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
url = MockDataFactory.randomString(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
name = MockDataFactory.randomString(),
|
||||
|
|
|
@ -646,7 +646,7 @@ class BlockViewDiffUtilTest {
|
|||
|
||||
val oldBlock = BlockView.Media.File(
|
||||
id = id,
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
indent = MockDataFactory.randomInt(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
|
|
|
@ -114,7 +114,7 @@ class BlockViewSearchTextTest {
|
|||
id = MockDataFactory.randomString(),
|
||||
name = MockDataFactory.randomString(),
|
||||
searchFields = listOf(field1),
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
indent = 0,
|
||||
|
|
|
@ -34,7 +34,7 @@ class BlockViewTest {
|
|||
fun `should return video block with view type Done`() {
|
||||
val block = BlockView.Media.Video(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
url = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
|
|
|
@ -10,29 +10,29 @@ import com.anytypeio.anytype.domain.config.Gateway
|
|||
class UrlBuilder(val gateway: Gateway) {
|
||||
|
||||
/**
|
||||
* Builds image url for given [hash]
|
||||
* Builds image url for given [path]
|
||||
*/
|
||||
fun image(hash: String?): Url = gateway.provide() + IMAGE_PATH + hash + DEFAULT_WIDTH_PARAM
|
||||
fun image(path: String): Url = gateway.provide() + IMAGE_PATH + path + DEFAULT_WIDTH_PARAM
|
||||
|
||||
/**
|
||||
* Builds original image url for given [hash]
|
||||
* Builds original image url for given [path]
|
||||
*/
|
||||
fun original(hash: String?): Url = gateway.provide() + IMAGE_PATH + hash
|
||||
fun original(path: String): Url = gateway.provide() + IMAGE_PATH + path
|
||||
|
||||
/**
|
||||
* Builds small image url for given [hash]
|
||||
* Builds small image url for given [path]
|
||||
*/
|
||||
fun thumbnail(hash: String): Url = gateway.provide() + IMAGE_PATH + hash + THUMBNAIL_WIDTH_PARAM
|
||||
fun thumbnail(path: String): Url = gateway.provide() + IMAGE_PATH + path + THUMBNAIL_WIDTH_PARAM
|
||||
|
||||
/**
|
||||
* Builds file url for given [hash]
|
||||
* Builds file url for given [path]
|
||||
*/
|
||||
fun file(hash: String?): Url = gateway.provide() + FILE_PATH + hash
|
||||
fun file(path: String): Url = gateway.provide() + FILE_PATH + path
|
||||
|
||||
/**
|
||||
* Builds video url for given [hash]
|
||||
* Builds video url for given [path]
|
||||
*/
|
||||
fun video(hash: String?): Url = gateway.provide() + FILE_PATH + hash
|
||||
fun video(path: String): Url = gateway.provide() + FILE_PATH + path
|
||||
|
||||
companion object {
|
||||
const val IMAGE_PATH = "/image/"
|
||||
|
|
|
@ -30,16 +30,6 @@ class UrlBuilderTest {
|
|||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return url with null at the end when image hash is null`() {
|
||||
val hash = null
|
||||
|
||||
val expected =
|
||||
gateway.provide() + UrlBuilder.IMAGE_PATH + null + UrlBuilder.DEFAULT_WIDTH_PARAM
|
||||
val actual = urlBuilder.image(hash)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return url without hash when image hash is empty`() {
|
||||
val hash = ""
|
||||
|
@ -58,15 +48,6 @@ class UrlBuilderTest {
|
|||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return url with null at the end when file hash is null`() {
|
||||
val hash = null
|
||||
|
||||
val expected = gateway.provide() + UrlBuilder.FILE_PATH + null
|
||||
val actual = urlBuilder.file(hash)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return url without hash when file hash is empty`() {
|
||||
val hash = ""
|
||||
|
@ -85,15 +66,6 @@ class UrlBuilderTest {
|
|||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return url with null at the end when video hash is null`() {
|
||||
val hash = null
|
||||
|
||||
val expected = gateway.provide() + UrlBuilder.FILE_PATH + null
|
||||
val actual = urlBuilder.video(hash)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return url without hash when video hash is empty`() {
|
||||
val hash = ""
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[versions]
|
||||
middlewareVersion = "v0.30.11"
|
||||
middlewareVersion = "v0.31.3"
|
||||
kotlinVersion = '1.8.22'
|
||||
|
||||
androidxCoreVersion = "1.12.0"
|
||||
|
|
|
@ -808,6 +808,7 @@
|
|||
<string name="anytype_analytics">Anytype Analytics</string>
|
||||
<string name="anytype_analytics_msg">Understanding how people use Anytype helps us improve the product. This version of Anytype includes the analytics code that protects your privacy.\nIt doesn\'t record the actual document\'s content but still allows us to understand how you use Anytype.\nStay subscribed to our mailing list, as we will soon announce a new release that enables you to opt-out.</string>
|
||||
<string name="retry">Retry</string>
|
||||
<string name="try_again">Try again</string>
|
||||
<string name="unsplash">Unsplash</string>
|
||||
<string name="cancel_deletion">Cancel deletion</string>
|
||||
<string name="logout_and_clear_local_data">Logout and clear local data</string>
|
||||
|
@ -1249,6 +1250,7 @@
|
|||
<string name="any_object_creation_menu_move_right">Move right</string>
|
||||
<string name="clipboard_panel_create_object_from_clipboard">Create object from clipboard</string>
|
||||
|
||||
<string name="block_media_error">Something went wrong, please try again</string>
|
||||
<string name="relation_value_create_new">Create \"%1$s\"</string>
|
||||
|
||||
</resources>
|
|
@ -28,6 +28,6 @@ class UnsplashMiddleware @Inject constructor(
|
|||
override fun download(id: Id): Hash {
|
||||
val request = Download.Request(pictureId = id).also { logger.logRequest(it) }
|
||||
val response = service.unsplashDownload(request = request).also { logger.logResponse(it) }
|
||||
return response.hash
|
||||
return response.objectId
|
||||
}
|
||||
}
|
|
@ -220,7 +220,7 @@ class BlockMiddleware(
|
|||
|
||||
override suspend fun uploadFile(
|
||||
command: Command.UploadFile
|
||||
): String = middleware.fileUpload(command).hash
|
||||
): String = middleware.fileUpload(command).objectId
|
||||
|
||||
override suspend fun downloadFile(
|
||||
command: Command.DownloadFile
|
||||
|
|
|
@ -826,13 +826,13 @@ class Middleware @Inject constructor(
|
|||
if (BuildConfig.DEBUG) logRequest(request)
|
||||
val response = service.fileUpload(request)
|
||||
if (BuildConfig.DEBUG) logResponse(response)
|
||||
return Response.Media.Upload(response.hash)
|
||||
return Response.Media.Upload(response.objectId)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun fileDownload(command: Command.DownloadFile): Rpc.File.Download.Response {
|
||||
val request = Rpc.File.Download.Request(
|
||||
hash = command.hash,
|
||||
objectId = command.objectId,
|
||||
path = command.path
|
||||
)
|
||||
if (BuildConfig.DEBUG) logRequest(request)
|
||||
|
|
|
@ -126,11 +126,11 @@ fun anytype.Event.Message.toCoreModels(
|
|||
with(event) {
|
||||
Event.Command.UpdateFileBlock(
|
||||
context = context,
|
||||
id = id,
|
||||
blockId = id,
|
||||
targetObjectId = targetObjectId?.value_,
|
||||
state = state?.value_?.toCoreModels(),
|
||||
type = type?.value_?.toCoreModels(),
|
||||
name = name?.value_,
|
||||
hash = hash?.value_,
|
||||
mime = mime?.value_,
|
||||
size = size?.value_
|
||||
)
|
||||
|
|
|
@ -330,7 +330,7 @@ fun MBlock.toCoreModelsDivider(): Block.Content.Divider {
|
|||
fun MBlock.toCoreModelsFile(): Block.Content.File {
|
||||
val content = checkNotNull(file_)
|
||||
return Block.Content.File(
|
||||
hash = content.hash,
|
||||
targetObjectId = content.targetObjectId,
|
||||
name = content.name,
|
||||
mime = content.mime,
|
||||
size = content.size,
|
||||
|
@ -551,6 +551,7 @@ fun MDVViewType.toCoreModels(): DVViewerType = when (this) {
|
|||
MDVViewType.Gallery -> DVViewerType.GALLERY
|
||||
MDVViewType.Kanban -> DVViewerType.BOARD
|
||||
MDVViewType.Calendar -> DVViewerType.CALENDAR
|
||||
MDVViewType.Graph -> DVViewerType.GRAPH
|
||||
}
|
||||
|
||||
fun MDVFilter.toCoreModels(): DVFilter = DVFilter(
|
||||
|
|
|
@ -113,7 +113,7 @@ fun Block.Content.Bookmark.State.toMiddlewareModel(): MBookmarkState = when (thi
|
|||
}
|
||||
|
||||
fun Block.Content.File.toMiddlewareModel(): MBFile = MBFile(
|
||||
hash = hash.orEmpty(),
|
||||
targetObjectId = targetObjectId.orEmpty(),
|
||||
name = name.orEmpty(),
|
||||
mime = mime.orEmpty(),
|
||||
size = size ?: 0,
|
||||
|
@ -340,6 +340,7 @@ fun Block.Content.DataView.Viewer.Type.toMiddlewareModel(): MDVViewType = when (
|
|||
Block.Content.DataView.Viewer.Type.GALLERY -> MDVViewType.Gallery
|
||||
Block.Content.DataView.Viewer.Type.BOARD -> MDVViewType.Kanban
|
||||
Block.Content.DataView.Viewer.Type.CALENDAR -> MDVViewType.Calendar
|
||||
Block.Content.DataView.Viewer.Type.GRAPH -> MDVViewType.Graph
|
||||
}
|
||||
|
||||
fun Block.Content.DataView.Sort.toMiddlewareModel(): MDVSort =
|
||||
|
|
|
@ -150,7 +150,7 @@ class MiddlewareEventChannelTest {
|
|||
@Test
|
||||
fun `should return UpdateBlockFile event`() {
|
||||
|
||||
val hash = "785687346534hfjdbsjfbds"
|
||||
val targetObjectId = "785687346534hfjdbsjfbds"
|
||||
val name = "video1.mp4"
|
||||
val mime = "video/*"
|
||||
val size = 999111L
|
||||
|
@ -162,7 +162,7 @@ class MiddlewareEventChannelTest {
|
|||
|
||||
val msg = anytype.Event.Block.Set.File(
|
||||
id = id,
|
||||
hash = anytype.Event.Block.Set.File.Hash(hash),
|
||||
targetObjectId = anytype.Event.Block.Set.File.TargetObjectId(targetObjectId),
|
||||
mime = anytype.Event.Block.Set.File.Mime(mime),
|
||||
size = anytype.Event.Block.Set.File.Size(size),
|
||||
type = anytype.Event.Block.Set.File.Type(type),
|
||||
|
@ -181,8 +181,8 @@ class MiddlewareEventChannelTest {
|
|||
val expected = listOf(
|
||||
Event.Command.UpdateFileBlock(
|
||||
context = context,
|
||||
id = id,
|
||||
hash = hash,
|
||||
blockId = id,
|
||||
targetObjectId = targetObjectId,
|
||||
mime = mime,
|
||||
size = size,
|
||||
type = com.anytypeio.anytype.core_models.Block.Content.File.Type.VIDEO,
|
||||
|
@ -220,7 +220,7 @@ class MiddlewareEventChannelTest {
|
|||
val expected = listOf(
|
||||
Event.Command.UpdateFileBlock(
|
||||
context = context,
|
||||
id = id
|
||||
blockId = id
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ class DocumentExternalEventReducer : StateReducer<List<Block>, Event> {
|
|||
val content = block.content<Block.Content.File>()
|
||||
block.copy(
|
||||
content = content.copy(
|
||||
hash = event.hash ?: content.hash,
|
||||
targetObjectId = event.targetObjectId ?: content.targetObjectId,
|
||||
name = event.name ?: content.name,
|
||||
mime = event.mime ?: content.mime,
|
||||
size = event.size ?: content.size,
|
||||
|
@ -83,7 +83,7 @@ class DocumentExternalEventReducer : StateReducer<List<Block>, Event> {
|
|||
)
|
||||
)
|
||||
},
|
||||
target = { block -> block.id == event.id }
|
||||
target = { block -> block.id == event.blockId }
|
||||
)
|
||||
is Event.Command.BookmarkGranularChange -> state.replace(
|
||||
replacement = { block ->
|
||||
|
|
|
@ -196,6 +196,7 @@ import com.anytypeio.anytype.presentation.editor.selection.updateTableBlockTab
|
|||
import com.anytypeio.anytype.presentation.editor.template.SelectTemplateViewState
|
||||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.extension.getProperObjectName
|
||||
import com.anytypeio.anytype.presentation.extension.getUrlForFileBlock
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsBlockActionEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsBlockAlignEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsBlockBackgroundEvent
|
||||
|
@ -1806,6 +1807,7 @@ class EditorViewModel(
|
|||
needSortByDownloads = true
|
||||
if (content.state == Content.File.State.DONE) {
|
||||
targetActions.addIfNotExists(ActionItemType.Download)
|
||||
targetActions.addIfNotExists(ActionItemType.OpenObject)
|
||||
} else {
|
||||
excludedActions.add(ActionItemType.Download)
|
||||
}
|
||||
|
@ -3608,6 +3610,13 @@ class EditorViewModel(
|
|||
else -> Unit
|
||||
}
|
||||
}
|
||||
is ListenerType.Bookmark.Upload -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit -> Unit
|
||||
EditorMode.Select -> onBlockMultiSelectClicked(clicked.target)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
is ListenerType.Bookmark.Error -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit -> onFailedBookmarkClicked(clicked.item)
|
||||
|
@ -3647,18 +3656,21 @@ class EditorViewModel(
|
|||
is ListenerType.Picture.View -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit, EditorMode.Locked -> {
|
||||
val target = blocks.find { it.id == clicked.target }
|
||||
if (target != null) {
|
||||
val content = target.content
|
||||
check(content is Content.File)
|
||||
val fileBlock = blocks.find { it.id == clicked.target }
|
||||
val url = urlBuilder.getUrlForFileBlock(
|
||||
fileBlock = fileBlock,
|
||||
isOriginalImage = true
|
||||
)
|
||||
if (url != null ) {
|
||||
dispatch(
|
||||
Command.OpenFullScreenImage(
|
||||
target = clicked.target,
|
||||
url = urlBuilder.original(content.hash)
|
||||
url = url
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Timber.e("Could not find target for picture")
|
||||
Timber.e("Block is not File or with wrong state, can't proceed with download")
|
||||
sendToast("Something went wrong. Couldn't open image")
|
||||
}
|
||||
}
|
||||
EditorMode.Select -> onBlockMultiSelectClicked(clicked.target)
|
||||
|
@ -4118,17 +4130,21 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onFileClicked(id: String) {
|
||||
val file = blocks.find { it.id == id }
|
||||
if (file != null && file.content is Content.File) {
|
||||
val cnt = (file.content as Content.File)
|
||||
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 = id,
|
||||
mime = cnt.mime.orEmpty(),
|
||||
uri = urlBuilder.file(cnt.hash)
|
||||
id = blockId,
|
||||
uri = url
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Timber.e("Block is not File or with wrong state, can't proceed with open")
|
||||
sendToast("Something went wrong. Couldn't open file.")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4145,7 +4161,7 @@ class EditorViewModel(
|
|||
viewModelScope.launch {
|
||||
orchestrator.proxies.intents.send(
|
||||
Media.ShareFile(
|
||||
hash = content.hash.orEmpty(),
|
||||
objectId = content.targetObjectId.orEmpty(),
|
||||
name = content.name.orEmpty(),
|
||||
type = content.type,
|
||||
onDownloaded = onDownloaded
|
||||
|
@ -4157,30 +4173,29 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun startDownloadingFile(id: String) {
|
||||
fun startDownloadingFile(blockId: Id) {
|
||||
|
||||
Timber.d("startDownloadingFile, id:[$id]")
|
||||
Timber.d("startDownloadingFile, for block:[$blockId]")
|
||||
|
||||
sendToast("Downloading file in background...")
|
||||
|
||||
val block = blocks.firstOrNull { it.id == id }
|
||||
val content = block?.content
|
||||
|
||||
if (content is Content.File && content.state == Content.File.State.DONE) {
|
||||
val fileBlock = blocks.firstOrNull { it.id == blockId }
|
||||
val fileContent = fileBlock?.content as? Content.File
|
||||
val url = urlBuilder.getUrlForFileBlock(fileBlock)
|
||||
|
||||
if (fileContent != null && url != null) {
|
||||
viewModelScope.launch {
|
||||
orchestrator.proxies.intents.send(
|
||||
Media.DownloadFile(
|
||||
url = when (content.type) {
|
||||
Content.File.Type.IMAGE -> urlBuilder.image(content.hash)
|
||||
else -> urlBuilder.file(content.hash)
|
||||
},
|
||||
name = content.name.orEmpty(),
|
||||
type = content.type
|
||||
url = url,
|
||||
name = fileContent.name.orEmpty(),
|
||||
type = fileContent.type
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.e("Block is not File or with wrong state, can't proceed with download")
|
||||
sendToast("Something went wrong. Couldn't download file.")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5581,6 +5596,18 @@ class EditorViewModel(
|
|||
sendToast("This bookmark doesn’t have a source.")
|
||||
}
|
||||
}
|
||||
is Content.File -> {
|
||||
val target = content.targetObjectId
|
||||
if (target != null) {
|
||||
proceedWithOpeningObject(target)
|
||||
viewModelScope.sendAnalyticsOpenAsObject(
|
||||
analytics = analytics,
|
||||
type = EventsDictionary.Type.bookmark
|
||||
)
|
||||
} else {
|
||||
sendToast("This object doesn’t have a target id")
|
||||
}
|
||||
}
|
||||
else -> sendToast("Unexpected object")
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -31,7 +31,6 @@ sealed class Command {
|
|||
*/
|
||||
data class OpenFileByDefaultApp(
|
||||
val id: String,
|
||||
val mime: String,
|
||||
val uri: String
|
||||
) : Command()
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ sealed class Intent {
|
|||
) : Media()
|
||||
|
||||
class ShareFile(
|
||||
val hash: Hash,
|
||||
val objectId: Id,
|
||||
val name: String,
|
||||
val type: Block.Content.File.Type?,
|
||||
val onDownloaded: (Uri) -> Unit
|
||||
|
|
|
@ -449,7 +449,7 @@ class Orchestrator(
|
|||
is Intent.Media.ShareFile -> {
|
||||
documentFileShareDownloader.async(
|
||||
params = MiddlewareShareDownloader.Params(
|
||||
hash = intent.hash,
|
||||
objectId = intent.objectId,
|
||||
name = intent.name
|
||||
)
|
||||
).suspendFold(
|
||||
|
|
|
@ -113,6 +113,10 @@ fun List<BlockView>.singleStylingMode(
|
|||
mode = BlockView.Mode.READ,
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.Upload.Bookmark -> view.copy(
|
||||
mode = BlockView.Mode.READ,
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.MediaPlaceholder.File -> view.copy(
|
||||
mode = BlockView.Mode.READ,
|
||||
isSelected = isSelected
|
||||
|
@ -263,6 +267,10 @@ fun List<BlockView>.enterSAM(
|
|||
mode = BlockView.Mode.READ,
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.Upload.Bookmark -> view.copy(
|
||||
mode = BlockView.Mode.READ,
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.MediaPlaceholder.File -> view.copy(
|
||||
mode = BlockView.Mode.READ,
|
||||
isSelected = isSelected
|
||||
|
@ -458,6 +466,7 @@ fun List<BlockView>.updateCursorAndEditMode(
|
|||
is BlockView.Upload.File -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.Upload.Video -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.Upload.Picture -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.Upload.Bookmark -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.MediaPlaceholder.File -> view.copy(
|
||||
mode = BlockView.Mode.EDIT,
|
||||
isSelected = false
|
||||
|
@ -518,6 +527,7 @@ fun List<BlockView>.toReadMode(): List<BlockView> = map { view ->
|
|||
is BlockView.Upload.File -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Upload.Video -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Upload.Picture -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.Upload.Bookmark -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.MediaPlaceholder.File -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.MediaPlaceholder.Video -> view.copy(mode = BlockView.Mode.READ)
|
||||
is BlockView.MediaPlaceholder.Bookmark -> view.copy(mode = BlockView.Mode.READ)
|
||||
|
@ -550,6 +560,7 @@ fun List<BlockView>.toEditMode(): List<BlockView> = map { view ->
|
|||
is BlockView.Upload.File -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.Upload.Video -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.Upload.Picture -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.Upload.Bookmark -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false)
|
||||
is BlockView.MediaPlaceholder.File -> view.copy(
|
||||
mode = BlockView.Mode.EDIT,
|
||||
isSelected = false
|
||||
|
@ -1065,6 +1076,7 @@ fun BlockView.updateSelection(newSelection: Boolean) = when (this) {
|
|||
is BlockView.MediaPlaceholder.Picture -> copy(isSelected = newSelection)
|
||||
is BlockView.Error.Picture -> copy(isSelected = newSelection)
|
||||
is BlockView.Upload.Picture -> copy(isSelected = newSelection)
|
||||
is BlockView.Upload.Bookmark -> copy(isSelected = newSelection)
|
||||
is BlockView.DividerLine -> copy(isSelected = newSelection)
|
||||
is BlockView.DividerDots -> copy(isSelected = newSelection)
|
||||
is BlockView.Code -> copy(isSelected = newSelection)
|
||||
|
|
|
@ -11,6 +11,7 @@ sealed interface ListenerType {
|
|||
sealed class Bookmark : ListenerType {
|
||||
data class View(val item: BlockView.Media.Bookmark) : Bookmark()
|
||||
data class Placeholder(val target: String) : Bookmark()
|
||||
data class Upload(val target: String) : File()
|
||||
data class Error(val item: BlockView.Error.Bookmark) : Bookmark()
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ private fun createBaseMentionMark(
|
|||
)
|
||||
}
|
||||
|
||||
if (!image.isNullOrEmpty()) {
|
||||
if (!image.isNullOrBlank()) {
|
||||
return Markup.Mark.Mention.WithImage(
|
||||
from = from,
|
||||
to = to,
|
||||
|
|
|
@ -780,7 +780,8 @@ sealed class BlockView : ViewType {
|
|||
override val mode: Mode = Mode.EDIT,
|
||||
override val isSelected: Boolean = false,
|
||||
override val background: ThemeColor = ThemeColor.DEFAULT,
|
||||
override val decorations: List<Decoration> = emptyList()
|
||||
override val decorations: List<Decoration> = emptyList(),
|
||||
val name: String? = null
|
||||
) : Error() {
|
||||
override fun getViewType() = HOLDER_FILE_ERROR
|
||||
}
|
||||
|
@ -795,7 +796,8 @@ sealed class BlockView : ViewType {
|
|||
override val mode: Mode = Mode.EDIT,
|
||||
override val isSelected: Boolean = false,
|
||||
override val background: ThemeColor = ThemeColor.DEFAULT,
|
||||
override val decorations: List<Decoration> = emptyList()
|
||||
override val decorations: List<Decoration> = emptyList(),
|
||||
val name: String? = null
|
||||
) : Error() {
|
||||
override fun getViewType() = HOLDER_VIDEO_ERROR
|
||||
}
|
||||
|
@ -809,7 +811,8 @@ sealed class BlockView : ViewType {
|
|||
override val mode: Mode = Mode.EDIT,
|
||||
override val isSelected: Boolean = false,
|
||||
override val background: ThemeColor = ThemeColor.DEFAULT,
|
||||
override val decorations: List<Decoration> = emptyList()
|
||||
override val decorations: List<Decoration> = emptyList(),
|
||||
val name: String? = null
|
||||
) : Error() {
|
||||
override fun getViewType() = HOLDER_PICTURE_ERROR
|
||||
}
|
||||
|
@ -997,8 +1000,9 @@ sealed class BlockView : ViewType {
|
|||
val size: Long?,
|
||||
val name: String?,
|
||||
val mime: String?,
|
||||
val hash: String?,
|
||||
val url: String
|
||||
val targetObjectId: Id,
|
||||
val url: String,
|
||||
val fileExt: String? = null
|
||||
) : Media(), Searchable {
|
||||
override fun getViewType() = HOLDER_FILE
|
||||
}
|
||||
|
@ -1016,7 +1020,7 @@ sealed class BlockView : ViewType {
|
|||
val size: Long?,
|
||||
val name: String?,
|
||||
val mime: String?,
|
||||
val hash: String?,
|
||||
val targetObjectId: Id,
|
||||
val url: String
|
||||
) : Media() {
|
||||
override fun getViewType() = HOLDER_VIDEO
|
||||
|
@ -1067,8 +1071,8 @@ sealed class BlockView : ViewType {
|
|||
val size: Long?,
|
||||
val name: String?,
|
||||
val mime: String?,
|
||||
val hash: String?,
|
||||
val url: String
|
||||
val targetObjectId: Id,
|
||||
val url: String,
|
||||
) : Media() {
|
||||
override fun getViewType() = HOLDER_PICTURE
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ import com.anytypeio.anytype.presentation.relations.BasicObjectCoverWrapper
|
|||
import com.anytypeio.anytype.presentation.relations.BlockFieldsCoverWrapper
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
|
||||
import com.anytypeio.anytype.presentation.relations.getCover
|
||||
import com.anytypeio.anytype.presentation.relations.isSystemKey
|
||||
import com.anytypeio.anytype.presentation.relations.linksFeaturedRelation
|
||||
import com.anytypeio.anytype.presentation.relations.objectTypeRelation
|
||||
import com.anytypeio.anytype.presentation.relations.view
|
||||
|
@ -635,7 +634,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
indent = indent,
|
||||
selection = selection,
|
||||
isPreviousBlockMedia = isPreviousBlockMedia,
|
||||
schema = blockDecorationScheme
|
||||
schema = blockDecorationScheme,
|
||||
details = details
|
||||
)
|
||||
)
|
||||
isPreviousBlockMedia = true
|
||||
|
@ -1265,8 +1265,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
url = obj.source.orEmpty(),
|
||||
title = obj.name,
|
||||
description = obj.description,
|
||||
imageUrl = obj.picture?.ifEmpty { null }?.let { urlBuilder.image(it) },
|
||||
faviconUrl = obj.iconImage?.ifEmpty { null }?.let { urlBuilder.image(it) },
|
||||
imageUrl = obj.picture?.takeIf { it.isNotBlank() }?.let { urlBuilder.image(it) },
|
||||
faviconUrl = obj.iconImage?.takeIf { it.isNotBlank() }?.let { urlBuilder.image(it) },
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
isSelected = checkIfSelected(
|
||||
|
@ -1336,10 +1336,11 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
indent: Int,
|
||||
selection: Set<Id>,
|
||||
isPreviousBlockMedia: Boolean,
|
||||
schema: NestedDecorationData
|
||||
schema: NestedDecorationData,
|
||||
details: Block.Details
|
||||
): BlockView = when (content.type) {
|
||||
Content.File.Type.IMAGE -> content.toPictureView(
|
||||
id = block.id,
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1350,10 +1351,11 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPreviousBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block)
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.FILE -> content.toFileView(
|
||||
id = block.id,
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1364,10 +1366,11 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block)
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.VIDEO -> content.toVideoView(
|
||||
id = block.id,
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1378,10 +1381,11 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block)
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.AUDIO -> content.toFileView(
|
||||
id = block.id,
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1392,10 +1396,11 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block)
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.PDF -> content.toFileView(
|
||||
id = block.id,
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1406,10 +1411,11 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block)
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
Content.File.Type.NONE -> content.toFileView(
|
||||
id = block.id,
|
||||
blockId = block.id,
|
||||
urlBuilder = urlBuilder,
|
||||
indent = indent,
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1420,7 +1426,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
),
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPrevBlockMedia = isPreviousBlockMedia,
|
||||
decorations = schema.toBlockViewDecoration(block)
|
||||
decorations = schema.toBlockViewDecoration(block),
|
||||
details = details
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected file type: ${content.type}")
|
||||
}
|
||||
|
@ -1474,15 +1481,9 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
mode = blockMode,
|
||||
id = block.id,
|
||||
text = content.text,
|
||||
emoji = details.details[root.id]?.iconEmoji?.let { name ->
|
||||
name.ifEmpty { null }
|
||||
},
|
||||
image = details.details[root.id]?.iconImage?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
urlBuilder.thumbnail(name)
|
||||
else
|
||||
null
|
||||
},
|
||||
emoji = details.details[root.id]?.iconEmoji?.takeIf { it.isNotBlank() },
|
||||
image = details.details[root.id]?.iconImage?.takeIf { it.isNotBlank() }
|
||||
?.let { urlBuilder.thumbnail(it) },
|
||||
isFocused = resolveIsFocused(focus, block),
|
||||
cursor = cursor,
|
||||
coverColor = coverContainer.coverColor,
|
||||
|
@ -1512,11 +1513,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
mode = blockMode,
|
||||
id = block.id,
|
||||
text = content.text,
|
||||
image = details.details[root.id]?.iconImage?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
urlBuilder.thumbnail(name)
|
||||
else
|
||||
null
|
||||
image = details.details[root.id]?.iconImage?.takeIf { it.isNotBlank() }?.let {
|
||||
urlBuilder.thumbnail(it)
|
||||
},
|
||||
spaceGradient = null,
|
||||
isFocused = resolveIsFocused(focus, block),
|
||||
|
@ -1533,11 +1531,9 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
mode = blockMode,
|
||||
id = block.id,
|
||||
text = content.text,
|
||||
emoji = details.details[root.id]?.iconEmoji?.let { name ->
|
||||
name.ifEmpty { null }
|
||||
},
|
||||
emoji = details.details[root.id]?.iconEmoji?.takeIf { it.isNotBlank() },
|
||||
image = details.details[root.id]?.iconImage?.let { image ->
|
||||
if (image.isNotEmpty() && layout != ObjectType.Layout.BOOKMARK)
|
||||
if (image.isNotBlank() && layout != ObjectType.Layout.BOOKMARK)
|
||||
urlBuilder.thumbnail(image)
|
||||
else
|
||||
null
|
||||
|
@ -1557,14 +1553,9 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
mode = blockMode,
|
||||
id = block.id,
|
||||
text = content.text,
|
||||
emoji = details.details[root.id]?.iconEmoji?.let { name ->
|
||||
name.ifEmpty { null }
|
||||
},
|
||||
image = details.details[root.id]?.iconImage?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
urlBuilder.thumbnail(name)
|
||||
else
|
||||
null
|
||||
emoji = details.details[root.id]?.iconEmoji?.takeIf { it.isNotBlank() },
|
||||
image = details.details[root.id]?.iconImage?.takeIf { it.isNotBlank() }?.let {
|
||||
urlBuilder.thumbnail(it)
|
||||
},
|
||||
isFocused = resolveIsFocused(focus, block),
|
||||
cursor = cursor,
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package com.anytypeio.anytype.presentation.extension
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
|
||||
fun UrlBuilder.getUrlForFileBlock(
|
||||
fileBlock: Block?,
|
||||
isOriginalImage: Boolean = false,
|
||||
isThumbnail: Boolean = false
|
||||
): Url? {
|
||||
if (fileBlock == null) return null
|
||||
val fileContent = fileBlock.content as? Block.Content.File ?: return null
|
||||
return getUrlForFileContent(fileContent, isOriginalImage, isThumbnail)
|
||||
}
|
||||
|
||||
fun UrlBuilder.getUrlForFileContent(
|
||||
fileContent: Block.Content.File,
|
||||
isOriginalImage: Boolean = false,
|
||||
isThumbnail: Boolean = false
|
||||
): Url? {
|
||||
val targetObjectId = fileContent.targetObjectId
|
||||
if (fileContent.state != Block.Content.File.State.DONE || targetObjectId.isNullOrBlank()) {
|
||||
return null
|
||||
}
|
||||
return getUrlBasedOnType(fileContent.type, targetObjectId, isOriginalImage, isThumbnail)
|
||||
}
|
||||
|
||||
private fun UrlBuilder.getUrlBasedOnType(
|
||||
fileType: Block.Content.File.Type?,
|
||||
targetObjectId: String,
|
||||
isOriginalImage: Boolean,
|
||||
isThumbnail: Boolean
|
||||
): Url? {
|
||||
return when (fileType) {
|
||||
Block.Content.File.Type.IMAGE -> {
|
||||
when {
|
||||
isOriginalImage -> original(targetObjectId)
|
||||
isThumbnail -> thumbnail(targetObjectId)
|
||||
else -> image(targetObjectId)
|
||||
}
|
||||
}
|
||||
|
||||
Block.Content.File.Type.VIDEO -> video(targetObjectId)
|
||||
Block.Content.File.Type.FILE,
|
||||
Block.Content.File.Type.PDF,
|
||||
Block.Content.File.Type.AUDIO -> file(targetObjectId)
|
||||
|
||||
Block.Content.File.Type.NONE, null -> null
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@ import com.anytypeio.anytype.presentation.editor.editor.mention.createMentionMar
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.Alignment
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.UiBlock
|
||||
import com.anytypeio.anytype.presentation.extension.getUrlForFileBlock
|
||||
import com.anytypeio.anytype.presentation.extension.getUrlForFileContent
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectLayoutView
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectTypeView
|
||||
import com.anytypeio.anytype.presentation.sets.buildGridRow
|
||||
|
@ -28,17 +30,18 @@ import com.anytypeio.anytype.presentation.templates.TemplateObjectTypeView
|
|||
import timber.log.Timber
|
||||
|
||||
fun Block.Content.File.toPictureView(
|
||||
id: String,
|
||||
blockId: String,
|
||||
urlBuilder: UrlBuilder,
|
||||
indent: Int,
|
||||
mode: BlockView.Mode,
|
||||
isSelected: Boolean = false,
|
||||
background: ThemeColor,
|
||||
isPreviousBlockMedia: Boolean,
|
||||
decorations: List<BlockView.Decoration>
|
||||
decorations: List<BlockView.Decoration>,
|
||||
details: Block.Details = Block.Details()
|
||||
): BlockView = when (state) {
|
||||
Block.Content.File.State.EMPTY -> BlockView.MediaPlaceholder.Picture(
|
||||
id = id,
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
|
@ -47,49 +50,70 @@ fun Block.Content.File.toPictureView(
|
|||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.UPLOADING -> BlockView.Upload.Picture(
|
||||
id = id,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.DONE -> BlockView.Media.Picture(
|
||||
id = id,
|
||||
size = size,
|
||||
name = name,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
url = urlBuilder.image(hash),
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
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.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
|
||||
)
|
||||
|
||||
} else {
|
||||
Timber.w("Could not build picture view for block $blockId")
|
||||
BlockView.Error.Picture(
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
)
|
||||
}
|
||||
}
|
||||
Block.Content.File.State.ERROR -> BlockView.Error.Picture(
|
||||
id = id,
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
decorations = decorations,
|
||||
name = name
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected state: $state")
|
||||
}
|
||||
|
||||
fun Block.Content.File.toVideoView(
|
||||
id: String,
|
||||
blockId: Id,
|
||||
urlBuilder: UrlBuilder,
|
||||
indent: Int,
|
||||
mode: BlockView.Mode,
|
||||
isSelected: Boolean = false,
|
||||
background: ThemeColor,
|
||||
isPrevBlockMedia: Boolean,
|
||||
decorations: List<BlockView.Decoration>
|
||||
decorations: List<BlockView.Decoration>,
|
||||
details: Block.Details = Block.Details()
|
||||
): BlockView = when (state) {
|
||||
Block.Content.File.State.EMPTY -> BlockView.MediaPlaceholder.Video(
|
||||
id = id,
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
|
@ -98,49 +122,70 @@ fun Block.Content.File.toVideoView(
|
|||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.UPLOADING -> BlockView.Upload.Video(
|
||||
id = id,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.DONE -> BlockView.Media.Video(
|
||||
id = id,
|
||||
size = size,
|
||||
name = name,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
url = urlBuilder.video(hash),
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
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
|
||||
)
|
||||
|
||||
} else {
|
||||
Timber.w("Could not build video view for block $blockId")
|
||||
BlockView.Error.Video(
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
)
|
||||
}
|
||||
}
|
||||
Block.Content.File.State.ERROR -> BlockView.Error.Video(
|
||||
id = id,
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations
|
||||
decorations = decorations,
|
||||
name = name
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected state: $state")
|
||||
}
|
||||
|
||||
fun Block.Content.File.toFileView(
|
||||
id: String,
|
||||
blockId: String,
|
||||
urlBuilder: UrlBuilder,
|
||||
indent: Int,
|
||||
mode: BlockView.Mode,
|
||||
isSelected: Boolean = false,
|
||||
background: ThemeColor,
|
||||
isPrevBlockMedia: Boolean,
|
||||
decorations: List<BlockView.Decoration>
|
||||
decorations: List<BlockView.Decoration>,
|
||||
details: Block.Details = Block.Details()
|
||||
): BlockView = when (state) {
|
||||
Block.Content.File.State.EMPTY -> BlockView.MediaPlaceholder.File(
|
||||
id = id,
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
|
@ -149,33 +194,54 @@ fun Block.Content.File.toFileView(
|
|||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.UPLOADING -> BlockView.Upload.File(
|
||||
id = id,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
)
|
||||
Block.Content.File.State.DONE -> BlockView.Media.File(
|
||||
id = id,
|
||||
size = size,
|
||||
name = name,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
url = urlBuilder.video(hash),
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
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.File(
|
||||
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,
|
||||
fileExt = targetObject.fileExt
|
||||
)
|
||||
|
||||
} else {
|
||||
Timber.w("Could not build file view for block $blockId")
|
||||
BlockView.Error.File(
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
)
|
||||
}
|
||||
}
|
||||
Block.Content.File.State.ERROR -> BlockView.Error.File(
|
||||
id = id,
|
||||
id = blockId,
|
||||
indent = indent,
|
||||
mode = mode,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
decorations = decorations
|
||||
decorations = decorations,
|
||||
name = name
|
||||
)
|
||||
else -> throw IllegalStateException("Unexpected state: $state")
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package com.anytypeio.anytype.presentation.mapper
|
||||
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
|
||||
|
||||
fun ObjectWrapper.Basic.getImagePath(urlBuilder: UrlBuilder): String? {
|
||||
val image = this.iconImage
|
||||
return if (image.isNullOrBlank()) {
|
||||
null
|
||||
} else {
|
||||
urlBuilder.image(iconImage)
|
||||
}
|
||||
}
|
||||
|
||||
fun ObjectWrapper.Basic.getEmojiPath(): String? {
|
||||
val emoji = this.iconEmoji
|
||||
return if (emoji.isNullOrBlank()) {
|
||||
null
|
||||
} else {
|
||||
emoji
|
||||
}
|
||||
}
|
|
@ -152,7 +152,7 @@ class ObjectMenuViewModel(
|
|||
override fun onDiagnosticsClicked(ctx: Id) {
|
||||
jobs += viewModelScope.launch {
|
||||
debugTreeShareDownloader.stream(
|
||||
MiddlewareShareDownloader.Params(hash = ctx, name = "$ctx.zip")
|
||||
MiddlewareShareDownloader.Params(objectId = ctx, name = "$ctx.zip")
|
||||
).collect { result ->
|
||||
result.fold(
|
||||
onSuccess = { success ->
|
||||
|
|
|
@ -339,7 +339,7 @@ abstract class ObjectMenuViewModelBase(
|
|||
fun onDiagnosticsGoroutinesClicked(ctx: Id) {
|
||||
jobs += viewModelScope.launch {
|
||||
debugGoroutinesShareDownloader.stream(
|
||||
MiddlewareShareDownloader.Params(hash = ctx, name = "goroutines")
|
||||
MiddlewareShareDownloader.Params(objectId = ctx, name = "goroutines")
|
||||
).collect { result ->
|
||||
result.fold(
|
||||
onSuccess = { success -> commands.emit(Command.ShareDebugGoroutines(success.path)) },
|
||||
|
|
|
@ -21,15 +21,18 @@ fun CoverWrapper.getCover(
|
|||
when (type) {
|
||||
CoverType.UPLOADED_IMAGE,
|
||||
CoverType.UNSPLASH_IMAGE -> {
|
||||
coverImage = coverId?.let { id ->
|
||||
urlBuilder.image(id)
|
||||
val targetObjectId = coverId
|
||||
coverImage = if (!targetObjectId.isNullOrBlank()) {
|
||||
urlBuilder.image(targetObjectId)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
CoverType.BUNDLED_IMAGE -> {
|
||||
val hash = coverId?.let { id ->
|
||||
coverImageHashProvider.provide(id)
|
||||
}
|
||||
if (hash != null) coverImage = urlBuilder.image(hash)
|
||||
if (!hash.isNullOrBlank()) coverImage = urlBuilder.image(hash)
|
||||
}
|
||||
CoverType.COLOR -> {
|
||||
coverColor = coverId?.let { id ->
|
||||
|
|
|
@ -209,9 +209,7 @@ fun title(
|
|||
id = title.id,
|
||||
text = wrapper.name.orEmpty(),
|
||||
emoji = wrapper.iconEmoji.orNull(),
|
||||
image = wrapper.iconImage.orNull()?.let { hash ->
|
||||
urlBuilder.thumbnail(hash = hash)
|
||||
},
|
||||
image = wrapper.iconImage?.takeIf { it.isNotBlank() }?.let { urlBuilder.thumbnail(it) },
|
||||
coverImage = coverContainer.coverImage,
|
||||
coverColor = coverContainer.coverColor,
|
||||
coverGradient = coverContainer.coverGradient
|
||||
|
|
|
@ -235,6 +235,7 @@ class EditDataViewViewerViewModel(
|
|||
Block.Content.DataView.Viewer.Type.GALLERY -> ViewState.Gallery
|
||||
Block.Content.DataView.Viewer.Type.BOARD -> ViewState.Kanban
|
||||
Block.Content.DataView.Viewer.Type.CALENDAR -> ViewState.Calendar
|
||||
Block.Content.DataView.Viewer.Type.GRAPH -> ViewState.Graph
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,6 +282,7 @@ class EditDataViewViewerViewModel(
|
|||
object List : ViewState()
|
||||
object Kanban : ViewState()
|
||||
object Calendar: ViewState()
|
||||
object Graph : ViewState()
|
||||
data class Error(val msg: String) : ViewState()
|
||||
}
|
||||
}
|
|
@ -138,7 +138,7 @@ private suspend fun ObjectWrapper.Basic.mapToCoverItem(
|
|||
val preview = details[id]
|
||||
preview != null && preview.type.contains(IMAGE)
|
||||
}
|
||||
if (previewId != null) {
|
||||
if (!previewId.isNullOrBlank()) {
|
||||
coverImage = urlBuilder.image(previewId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -457,7 +457,7 @@ fun ObjectWrapper.Basic.toTemplateView(
|
|||
name = name.orEmpty(),
|
||||
targetTypeId = TypeId(targetObjectType.orEmpty()),
|
||||
emoji = if (!iconEmoji.isNullOrBlank()) iconEmoji else null,
|
||||
image = if (!iconImage.isNullOrBlank()) urlBuilder.thumbnail(iconImage!!) else null,
|
||||
image = iconImage?.takeIf { it.isNotBlank() }?.let { urlBuilder.thumbnail(it) },
|
||||
layout = layout ?: ObjectType.Layout.BASIC,
|
||||
coverColor = coverContainer?.coverColor,
|
||||
coverImage = coverContainer?.coverImage,
|
||||
|
|
|
@ -207,7 +207,7 @@ suspend fun List<ColumnView>.buildGridRow(
|
|||
type = type,
|
||||
name = name,
|
||||
emoji = emoji,
|
||||
image = image?.let { if (it.isEmpty()) null else builder.thumbnail(it) },
|
||||
image = image?.takeIf { it.isNotBlank() }?.let { builder.thumbnail(it) },
|
||||
cells = cells,
|
||||
layout = layout,
|
||||
isChecked = done,
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.presentation.util.downloader
|
|||
|
||||
import android.content.Context
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
|
@ -12,7 +13,7 @@ class DocumentFileShareDownloader(
|
|||
dispatchers: AppCoroutineDispatchers
|
||||
) : MiddlewareShareDownloader(context, uriFileProvider, dispatchers) {
|
||||
|
||||
override suspend fun downloadFile(hash: String, path: String) = repo.downloadFile(
|
||||
Command.DownloadFile(hash = hash, path = path)
|
||||
override suspend fun downloadFile(objectId: Id, path: String) = repo.downloadFile(
|
||||
Command.DownloadFile(objectId = objectId, path = path)
|
||||
)
|
||||
}
|
|
@ -2,7 +2,7 @@ package com.anytypeio.anytype.presentation.util.downloader
|
|||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import java.io.File
|
||||
|
@ -18,7 +18,7 @@ abstract class MiddlewareShareDownloader(
|
|||
) : ResultInteractor<MiddlewareShareDownloader.Params, MiddlewareShareDownloader.Response>(dispatchers.io) {
|
||||
|
||||
data class Params(
|
||||
val hash: Hash,
|
||||
val objectId: Id,
|
||||
val name: String
|
||||
)
|
||||
|
||||
|
@ -28,20 +28,20 @@ abstract class MiddlewareShareDownloader(
|
|||
)
|
||||
|
||||
/**
|
||||
* @param hash is a some middleware id
|
||||
* @param objectId id of Object File
|
||||
* @param path is local storage path to the file created
|
||||
* @return path to the file in the local storage
|
||||
* */
|
||||
abstract suspend fun downloadFile(hash: String, path: String): String
|
||||
abstract suspend fun downloadFile(objectId: Id, path: String): String
|
||||
|
||||
override suspend fun doWork(params: Params): Response {
|
||||
val cacheDir = context.cacheDir
|
||||
|
||||
require(cacheDir != null) { "Impossible to cache files!" }
|
||||
|
||||
val downloadFolder = File("${cacheDir.path}/${params.hash}").apply { mkdirs() }
|
||||
val downloadFolder = File("${cacheDir.path}/${params.objectId}").apply { mkdirs() }
|
||||
|
||||
val resultFilePath = "${cacheDir.path}/${params.hash}/${params.name}"
|
||||
val resultFilePath = "${cacheDir.path}/${params.objectId}/${params.name}"
|
||||
val resultFile = File(resultFilePath)
|
||||
|
||||
if (!resultFile.exists()) {
|
||||
|
@ -50,7 +50,12 @@ abstract class MiddlewareShareDownloader(
|
|||
if (tempDir.exists()) tempDir.deleteRecursively()
|
||||
tempDir.mkdirs()
|
||||
|
||||
val tempResult = File(downloadFile(params.hash, tempFileFolderPath))
|
||||
val tempResult = File(
|
||||
downloadFile(
|
||||
objectId = params.objectId,
|
||||
path = tempFileFolderPath
|
||||
)
|
||||
)
|
||||
|
||||
tempResult.renameTo(resultFile)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.anytypeio.anytype.analytics.base.Analytics
|
|||
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.Payload
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
|
@ -398,6 +399,7 @@ open class EditorViewModelTest {
|
|||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
builder = UrlBuilder(gateway)
|
||||
stubNetworkMode()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -406,6 +408,12 @@ open class EditorViewModelTest {
|
|||
verifyNoInteractions(interceptEvents)
|
||||
}
|
||||
|
||||
fun stubNetworkMode() {
|
||||
getNetworkMode.stub {
|
||||
onBlocking { run(Unit) } doReturn NetworkModeConfig()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should start opening page when requested`() {
|
||||
val param = OpenPage.Params(root, true)
|
||||
|
@ -2568,7 +2576,7 @@ open class EditorViewModelTest {
|
|||
params = eq(
|
||||
MiddlewareShareDownloader.Params(
|
||||
name = file.content<Block.Content.File>().name.orEmpty(),
|
||||
hash = file.content<Block.Content.File>().hash.orEmpty(),
|
||||
objectId = file.content<Block.Content.File>().targetObjectId.orEmpty(),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -2618,7 +2626,7 @@ open class EditorViewModelTest {
|
|||
|
||||
// TESTING
|
||||
|
||||
vm.startDownloadingFile(id = file.id)
|
||||
vm.startDownloadingFile(blockId = file.id)
|
||||
|
||||
runBlockingTest {
|
||||
verify(downloadFile, times(1)).invoke(
|
||||
|
@ -2626,7 +2634,7 @@ open class EditorViewModelTest {
|
|||
DownloadFile.Params(
|
||||
name = file.content<Block.Content.File>().name.orEmpty(),
|
||||
url = builder.file(
|
||||
hash = file.content<Block.Content.File>().hash
|
||||
path = file.content<Block.Content.File>().targetObjectId!!
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -3394,7 +3402,7 @@ open class EditorViewModelTest {
|
|||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
state = Block.Content.File.State.ERROR
|
||||
),
|
||||
|
@ -3469,7 +3477,7 @@ open class EditorViewModelTest {
|
|||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = MockDataFactory.randomString(),
|
||||
type = Block.Content.File.Type.VIDEO,
|
||||
state = Block.Content.File.State.ERROR
|
||||
),
|
||||
|
@ -3587,7 +3595,8 @@ open class EditorViewModelTest {
|
|||
background = ThemeColor.DEFAULT,
|
||||
style = BlockView.Decoration.Style.Card
|
||||
)
|
||||
)
|
||||
),
|
||||
name = file.content<Block.Content.File>().name.orEmpty()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
|
|||
val file = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
content = Block.Content.File(
|
||||
hash = MockDataFactory.randomUuid(),
|
||||
targetObjectId = MockDataFactory.randomUuid(),
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.DONE
|
||||
),
|
||||
|
@ -69,7 +69,7 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
|
|||
|
||||
// Launching operation that triggers a toast
|
||||
|
||||
vm.startDownloadingFile(id = file.id)
|
||||
vm.startDownloadingFile(blockId = file.id)
|
||||
|
||||
val subscription2 = launch { vm.toasts.collect { consumed.add(it) } }
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.StubTitle
|
|||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.ext.content
|
||||
import com.anytypeio.anytype.core_utils.common.EventWrapper
|
||||
import com.anytypeio.anytype.presentation.BuildConfig
|
||||
import com.anytypeio.anytype.presentation.MockBlockFactory
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
@ -21,6 +20,7 @@ import com.anytypeio.anytype.presentation.util.TXT
|
|||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import com.jraska.livedata.test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
@ -48,6 +48,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
stubGetNetworkMode()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -543,15 +544,18 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `should open file when clicking on file when page is locked`() {
|
||||
fun `should open file when clicking on file when page is locked`() = runTest {
|
||||
|
||||
// SETUP
|
||||
|
||||
val fileBlockId = MockDataFactory.randomUuid()
|
||||
val targetObjectId = MockDataFactory.randomUuid()
|
||||
|
||||
val file = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
id = fileBlockId,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = targetObjectId,
|
||||
type = Block.Content.File.Type.FILE,
|
||||
state = Block.Content.File.State.DONE
|
||||
),
|
||||
|
@ -565,17 +569,33 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
mapOf(Block.Fields.IS_LOCKED_KEY to true)
|
||||
),
|
||||
content = Block.Content.Smart,
|
||||
children = listOf(header.id, file.id)
|
||||
children = listOf(header.id, fileBlockId)
|
||||
),
|
||||
header,
|
||||
title,
|
||||
file
|
||||
)
|
||||
|
||||
val mimeType = "application/pdf"
|
||||
val fileName = "file.pdf"
|
||||
val fileSize = 1000.0
|
||||
|
||||
stubInterceptEvents()
|
||||
stubInterceptThreadStatus()
|
||||
stubOpenDocument(
|
||||
document = page
|
||||
document = page,
|
||||
details = Block.Details(
|
||||
mapOf(
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to targetObjectId,
|
||||
Relations.FILE_MIME_TYPE to mimeType,
|
||||
Relations.NAME to fileName,
|
||||
Relations.SIZE_IN_BYTES to fileSize
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
@ -593,13 +613,13 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
mode = BlockView.Mode.READ
|
||||
),
|
||||
BlockView.Media.File(
|
||||
id = file.id,
|
||||
id = fileBlockId,
|
||||
mode = BlockView.Mode.READ,
|
||||
hash = file.content<Block.Content.File>().hash,
|
||||
mime = null,
|
||||
name = null,
|
||||
size = null,
|
||||
url = builder.file(file.content<Block.Content.File>().hash),
|
||||
targetObjectId = targetObjectId,
|
||||
mime = mimeType,
|
||||
name = fileName,
|
||||
size = fileSize.toLong(),
|
||||
url = builder.file(targetObjectId),
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
background = ThemeColor.DEFAULT,
|
||||
|
@ -618,15 +638,14 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
|
||||
val testObserver = vm.commands.test()
|
||||
|
||||
vm.onClickListener(ListenerType.File.View(file.id))
|
||||
vm.onClickListener(ListenerType.File.View(fileBlockId))
|
||||
|
||||
// checking open-by-default-app command
|
||||
|
||||
testObserver.assertValue { value ->
|
||||
value is EventWrapper && value.peekContent() == Command.OpenFileByDefaultApp(
|
||||
id = file.id,
|
||||
uri = builder.file(file.content<Block.Content.File>().hash),
|
||||
mime = file.content<Block.Content.File>().mime.orEmpty()
|
||||
id = fileBlockId,
|
||||
uri = builder.file(targetObjectId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -636,11 +655,17 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
|
||||
// SETUP
|
||||
|
||||
val fileBlockId = MockDataFactory.randomUuid()
|
||||
val targetObjectId = MockDataFactory.randomUuid()
|
||||
val mimeType = "*/png"
|
||||
val fileName = "image.png"
|
||||
val fileSize = 1000.0
|
||||
|
||||
val picture = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
id = fileBlockId,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
hash = MockDataFactory.randomString(),
|
||||
targetObjectId = targetObjectId,
|
||||
type = Block.Content.File.Type.IMAGE,
|
||||
state = Block.Content.File.State.DONE
|
||||
),
|
||||
|
@ -664,7 +689,19 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
stubInterceptEvents()
|
||||
stubInterceptThreadStatus()
|
||||
stubOpenDocument(
|
||||
document = page
|
||||
document = page,
|
||||
details = Block.Details(
|
||||
mapOf(
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to targetObjectId,
|
||||
Relations.FILE_MIME_TYPE to mimeType,
|
||||
Relations.NAME to fileName,
|
||||
Relations.SIZE_IN_BYTES to fileSize
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
@ -684,11 +721,11 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
BlockView.Media.Picture(
|
||||
id = picture.id,
|
||||
mode = BlockView.Mode.READ,
|
||||
hash = picture.content<Block.Content.File>().hash,
|
||||
mime = null,
|
||||
name = null,
|
||||
size = null,
|
||||
url = builder.image(picture.content<Block.Content.File>().hash),
|
||||
targetObjectId = targetObjectId,
|
||||
mime = mimeType,
|
||||
name = fileName,
|
||||
size = fileSize.toLong(),
|
||||
url = builder.image(targetObjectId),
|
||||
indent = 0,
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
|
@ -715,7 +752,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
testObserver.assertValue { value ->
|
||||
value is EventWrapper && value.peekContent() == Command.OpenFullScreenImage(
|
||||
target = picture.id,
|
||||
url = builder.original(picture.content<Block.Content.File>().hash)
|
||||
url = builder.original(targetObjectId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
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.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.domain.config.Gateway
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup
|
||||
|
@ -20,6 +23,8 @@ class MapperExtensionKtTest {
|
|||
|
||||
private val urlBuilder: UrlBuilder get() = UrlBuilder(gateway)
|
||||
|
||||
private val targetObjectId : Id = "647tyhfgehf7ru"
|
||||
|
||||
@Before
|
||||
fun before() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
|
@ -33,18 +38,28 @@ class MapperExtensionKtTest {
|
|||
val indent = MockDataFactory.randomInt()
|
||||
|
||||
val name = "name"
|
||||
val size = 10000L
|
||||
val mime = "*/txt"
|
||||
val hash = "647tyhfgehf7ru"
|
||||
val state = Block.Content.File.State.DONE
|
||||
val type = Block.Content.File.Type.FILE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.NAME to name,
|
||||
Relations.SIZE_IN_BYTES to 10000.0,
|
||||
Relations.FILE_MIME_TYPE to mime,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = name,
|
||||
size = size,
|
||||
size = 10000L,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
targetObjectId = targetObjectId,
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
|
@ -53,15 +68,15 @@ class MapperExtensionKtTest {
|
|||
val expected = BlockView.Media.File(
|
||||
id = id,
|
||||
name = name,
|
||||
size = size,
|
||||
size = 10000L,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
targetObjectId = targetObjectId,
|
||||
mode = BlockView.Mode.EDIT,
|
||||
url = urlBuilder.video(hash),
|
||||
url = urlBuilder.video(targetObjectId),
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -79,7 +94,8 @@ class MapperExtensionKtTest {
|
|||
|
||||
val block = Block.Content.File(
|
||||
state = state,
|
||||
type = type
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val expected =
|
||||
|
@ -102,8 +118,8 @@ class MapperExtensionKtTest {
|
|||
|
||||
val block = Block.Content.File(
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val expected = BlockView.Error.File(id = id, indent = indent, decorations = emptyList())
|
||||
|
@ -125,7 +141,8 @@ class MapperExtensionKtTest {
|
|||
|
||||
val block = Block.Content.File(
|
||||
state = state,
|
||||
type = type
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val expected = BlockView.Upload.File(id = id, indent = indent)
|
||||
|
@ -142,7 +159,7 @@ class MapperExtensionKtTest {
|
|||
val indent = MockDataFactory.randomInt()
|
||||
|
||||
val name = "name"
|
||||
val size = 10000L
|
||||
val size = 10000.0
|
||||
val mime = "image/jpeg"
|
||||
val hash = "647tyhfgehf7ru"
|
||||
val state = Block.Content.File.State.DONE
|
||||
|
@ -150,27 +167,36 @@ class MapperExtensionKtTest {
|
|||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = name,
|
||||
size = size,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
targetObjectId = targetObjectId,
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
)
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.NAME to name,
|
||||
Relations.SIZE_IN_BYTES to size,
|
||||
Relations.FILE_MIME_TYPE to mime,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = BlockView.Media.Picture(
|
||||
id = id,
|
||||
name = name,
|
||||
size = size,
|
||||
size = size.toLong(),
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
targetObjectId = targetObjectId,
|
||||
url = urlBuilder.image(hash),
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -188,8 +214,8 @@ class MapperExtensionKtTest {
|
|||
|
||||
val block = Block.Content.File(
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val expected = BlockView.MediaPlaceholder.Picture(
|
||||
|
@ -215,8 +241,8 @@ class MapperExtensionKtTest {
|
|||
|
||||
val block = Block.Content.File(
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val expected = BlockView.Error.Picture(
|
||||
|
@ -243,7 +269,8 @@ class MapperExtensionKtTest {
|
|||
|
||||
val block = Block.Content.File(
|
||||
state = state,
|
||||
type = type
|
||||
type = type,
|
||||
targetObjectId = targetObjectId
|
||||
)
|
||||
|
||||
val expected = BlockView.Upload.Picture(id = id, indent = indent)
|
||||
|
@ -262,38 +289,47 @@ class MapperExtensionKtTest {
|
|||
val name = "name"
|
||||
val size = 10000L
|
||||
val mime = "video/mp4"
|
||||
val hash = "647tyhfgehf7ru"
|
||||
val targetObjectId = "647tyhfgehf7ru"
|
||||
val state = Block.Content.File.State.DONE
|
||||
val type = Block.Content.File.Type.VIDEO
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = name,
|
||||
size = size,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
targetObjectId = targetObjectId,
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
targetObjectId to Block.Fields(
|
||||
mapOf(
|
||||
Relations.NAME to name,
|
||||
Relations.SIZE_IN_BYTES to 10000.0,
|
||||
Relations.FILE_MIME_TYPE to mime,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val expected = BlockView.Media.Video(
|
||||
id = id,
|
||||
name = name,
|
||||
size = size,
|
||||
mime = mime,
|
||||
hash = hash,
|
||||
url = urlBuilder.video(hash),
|
||||
targetObjectId = targetObjectId,
|
||||
url = urlBuilder.video(targetObjectId),
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
val actual = block.toVideoView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList(), details)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return video block view empty params`() {
|
||||
fun `should return video block error view when target object id is empty`() {
|
||||
|
||||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
|
@ -304,22 +340,13 @@ class MapperExtensionKtTest {
|
|||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
hash = null,
|
||||
targetObjectId = null,
|
||||
state = state,
|
||||
type = type
|
||||
|
||||
)
|
||||
|
||||
val expected = BlockView.Media.Video(
|
||||
val expected = BlockView.Error.Video(
|
||||
id = id,
|
||||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
hash = null,
|
||||
url = urlBuilder.video(null),
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
|
@ -329,6 +356,90 @@ class MapperExtensionKtTest {
|
|||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return image block error view when target object id is empty`() {
|
||||
|
||||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
val indent = MockDataFactory.randomInt()
|
||||
|
||||
val state = Block.Content.File.State.DONE
|
||||
val type = Block.Content.File.Type.IMAGE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = null,
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
|
||||
val expected = BlockView.Error.Picture(
|
||||
id = id,
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toPictureView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return file block error view when target object id is empty`() {
|
||||
|
||||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
val indent = MockDataFactory.randomInt()
|
||||
|
||||
val state = Block.Content.File.State.DONE
|
||||
val type = Block.Content.File.Type.FILE
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = null,
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
|
||||
val expected = BlockView.Error.File(
|
||||
id = id,
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return file block error view when target object id is empty for pdf`() {
|
||||
|
||||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
val indent = MockDataFactory.randomInt()
|
||||
|
||||
val state = Block.Content.File.State.DONE
|
||||
val type = Block.Content.File.Type.PDF
|
||||
val mode = BlockView.Mode.EDIT
|
||||
|
||||
val block = Block.Content.File(
|
||||
targetObjectId = null,
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
|
||||
val expected = BlockView.Error.File(
|
||||
id = id,
|
||||
indent = indent,
|
||||
decorations = emptyList()
|
||||
)
|
||||
|
||||
val actual = block.toFileView(id, urlBuilder, indent, mode, false, ThemeColor.DEFAULT, false, emptyList())
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return placeholder video block view`() {
|
||||
|
||||
|
@ -344,7 +455,7 @@ class MapperExtensionKtTest {
|
|||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
hash = null,
|
||||
targetObjectId = null,
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
|
@ -375,7 +486,7 @@ class MapperExtensionKtTest {
|
|||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
hash = null,
|
||||
targetObjectId = null,
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
|
@ -405,7 +516,7 @@ class MapperExtensionKtTest {
|
|||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
hash = null,
|
||||
targetObjectId = null,
|
||||
state = state,
|
||||
type = type
|
||||
)
|
||||
|
@ -435,7 +546,7 @@ class MapperExtensionKtTest {
|
|||
name = null,
|
||||
size = null,
|
||||
mime = null,
|
||||
hash = null,
|
||||
targetObjectId = null,
|
||||
state = null,
|
||||
type = type
|
||||
)
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.junit.Test
|
|||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.doThrow
|
||||
import org.mockito.kotlin.stub
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNull
|
||||
|
@ -37,7 +36,7 @@ class ObjectWrapperExtensionsKtTest {
|
|||
|
||||
stubUrlBuilder(imageHash)
|
||||
|
||||
val result = obj.getImagePath(urlBuilder)
|
||||
val result = urlBuilder.image(obj.iconImage!!)
|
||||
|
||||
val expected = URL + imageHash
|
||||
|
||||
|
@ -47,87 +46,6 @@ class ObjectWrapperExtensionsKtTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return null image path from object wrapper when hash is null`() {
|
||||
|
||||
val imageHash: String? = null
|
||||
|
||||
val obj = ObjectWrapper.Basic(
|
||||
mapOf("iconImage" to imageHash)
|
||||
)
|
||||
|
||||
stubUrlBuilder(imageHash)
|
||||
|
||||
val result = obj.getImagePath(urlBuilder)
|
||||
|
||||
assertNull(actual = result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return null image path from object wrapper when hash is empty`() {
|
||||
|
||||
val imageHash = ""
|
||||
|
||||
val obj = ObjectWrapper.Basic(
|
||||
mapOf("iconImage" to imageHash)
|
||||
)
|
||||
|
||||
stubUrlBuilder(imageHash)
|
||||
|
||||
val result = obj.getImagePath(urlBuilder)
|
||||
|
||||
assertNull(actual = result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return null image path from object wrapper when hash is blank`() {
|
||||
|
||||
val imageHash = " "
|
||||
|
||||
val obj = ObjectWrapper.Basic(
|
||||
mapOf("iconImage" to imageHash)
|
||||
)
|
||||
|
||||
stubUrlBuilder(imageHash)
|
||||
|
||||
val result = obj.getImagePath(urlBuilder)
|
||||
|
||||
assertNull(actual = result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return proper emoji from object wrapper`() {
|
||||
|
||||
val emojiHash = "ycd79"
|
||||
|
||||
val obj = ObjectWrapper.Basic(
|
||||
mapOf("iconEmoji" to emojiHash)
|
||||
)
|
||||
|
||||
val result = obj.getEmojiPath()
|
||||
|
||||
val expected = emojiHash
|
||||
|
||||
assertEquals(
|
||||
expected = expected,
|
||||
actual = result
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return null emoji from object wrapper when emoji is null`() {
|
||||
|
||||
val emojiHash: String? = null
|
||||
|
||||
val obj = ObjectWrapper.Basic(
|
||||
mapOf("iconEmoji" to emojiHash)
|
||||
)
|
||||
|
||||
val result = obj.getEmojiPath()
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return null emoji from object wrapper when emoji is empty`() {
|
||||
|
||||
|
@ -137,7 +55,7 @@ class ObjectWrapperExtensionsKtTest {
|
|||
mapOf("iconEmoji" to emojiHash)
|
||||
)
|
||||
|
||||
val result = obj.getEmojiPath()
|
||||
val result = urlBuilder.image(obj.iconEmoji!!)
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
|
@ -151,7 +69,7 @@ class ObjectWrapperExtensionsKtTest {
|
|||
mapOf("iconEmoji" to emojiHash)
|
||||
)
|
||||
|
||||
val result = obj.getEmojiPath()
|
||||
val result = urlBuilder.image(obj.iconEmoji!!)
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
|
@ -226,15 +144,9 @@ class ObjectWrapperExtensionsKtTest {
|
|||
)
|
||||
}
|
||||
|
||||
fun stubUrlBuilder(hash: String?) {
|
||||
if (hash == null) {
|
||||
urlBuilder.stub {
|
||||
on { image(null) } doThrow RuntimeException("Should not happened")
|
||||
}
|
||||
} else {
|
||||
urlBuilder.stub {
|
||||
on { image(hash) } doReturn URL + hash
|
||||
}
|
||||
fun stubUrlBuilder(targetObjectId: String) {
|
||||
urlBuilder.stub {
|
||||
on { image(targetObjectId) } doReturn URL + targetObjectId
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,6 +59,7 @@ message Change {
|
|||
|
||||
StoreSliceUpdate storeSliceUpdate = 109;
|
||||
OriginalCreatedTimestampSet originalCreatedTimestampSet = 110;
|
||||
SetFileInfo setFileInfo = 111;
|
||||
}
|
||||
reserved 102,103,104; // old unsupported relation changes
|
||||
}
|
||||
|
@ -151,4 +152,8 @@ message Change {
|
|||
message OriginalCreatedTimestampSet {
|
||||
int64 ts = 1;
|
||||
}
|
||||
|
||||
message SetFileInfo {
|
||||
model.FileInfo fileInfo = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,12 +210,16 @@ message Rpc {
|
|||
message CreateSession {
|
||||
message Request {
|
||||
option (no_auth) = true;
|
||||
string mnemonic = 1;
|
||||
oneof auth {
|
||||
string mnemonic = 1; // cold auth
|
||||
string appKey = 2; // persistent app key, that can be used to restore session
|
||||
}
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string token = 2;
|
||||
string appToken = 3; // in case of mnemonic auth, need to be persisted by client
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
@ -640,8 +644,63 @@ message Rpc {
|
|||
LocalOnly = 1; // disable any-sync network and use only local p2p nodes
|
||||
CustomConfig = 2; // use config provided in networkConfigFilePath
|
||||
}
|
||||
}
|
||||
|
||||
message LocalLink {
|
||||
message NewChallenge {
|
||||
message Request {
|
||||
option (no_auth) = true;
|
||||
string appName = 1; // just for info, not secure to rely on
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string challengeId = 2;
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
|
||||
ACCOUNT_IS_NOT_RUNNING = 101;
|
||||
TOO_MANY_REQUESTS = 102; // protection from overuse
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message SolveChallenge {
|
||||
message Request {
|
||||
option (no_auth) = true;
|
||||
string challengeId = 1;
|
||||
string answer = 2;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string sessionToken = 2; // ephemeral token for the session
|
||||
string appKey = 3; // persistent key, that can be used to restore session via CreateSession
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
|
||||
ACCOUNT_IS_NOT_RUNNING = 101;
|
||||
INVALID_CHALLENGE_ID = 102;
|
||||
CHALLENGE_ATTEMPTS_EXCEEDED = 103;
|
||||
INCORRECT_ANSWER = 104;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message Workspace {
|
||||
message GetCurrent {
|
||||
message Request {
|
||||
|
@ -1120,6 +1179,33 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
message CreateFromUrl {
|
||||
message Request {
|
||||
string spaceId = 1;
|
||||
string objectTypeUniqueKey = 2;
|
||||
string url = 3;
|
||||
google.protobuf.Struct details = 4;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string objectId = 2;
|
||||
google.protobuf.Struct details = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message BookmarkFetch {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
|
@ -2572,6 +2658,32 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
message SpaceOffload {
|
||||
message Request {
|
||||
string spaceId = 1;
|
||||
}
|
||||
message Response {
|
||||
Error error = 1;
|
||||
int32 filesOffloaded = 2;
|
||||
uint64 bytesOffloaded = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
NODE_NOT_STARTED = 103;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message ListOffload {
|
||||
message Request {
|
||||
repeated string onlyIds = 1; // empty means all
|
||||
|
@ -2605,12 +2717,13 @@ message Rpc {
|
|||
anytype.model.Block.Content.File.Type type = 3;
|
||||
bool disableEncryption = 4; // deprecated, has no affect, GO-1926
|
||||
anytype.model.Block.Content.File.Style style = 5;
|
||||
|
||||
google.protobuf.Struct details = 7; // additional details for file object
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string hash = 2;
|
||||
string objectId = 2;
|
||||
google.protobuf.Struct details = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -2626,7 +2739,7 @@ message Rpc {
|
|||
}
|
||||
message Download {
|
||||
message Request {
|
||||
string hash = 1;
|
||||
string objectId = 1;
|
||||
string path = 2; // path to save file. Temp directory is used if empty
|
||||
}
|
||||
|
||||
|
@ -2942,7 +3055,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string hash = 2;
|
||||
string objectId = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -3658,6 +3771,27 @@ message Rpc {
|
|||
message Response {
|
||||
Error error = 1;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message Preview {
|
||||
message Request {
|
||||
string html = 1;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
repeated anytype.model.Block blocks = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
|
|
@ -20,6 +20,7 @@ message Event {
|
|||
Account.Details accountDetails = 201;
|
||||
Account.Config.Update accountConfigUpdate = 202;
|
||||
Account.Update accountUpdate = 203;
|
||||
Account.LinkChallenge accountLinkChallenge = 204;
|
||||
|
||||
Object.Details.Set objectDetailsSet = 16;
|
||||
Object.Details.Amend objectDetailsAmend = 50;
|
||||
|
@ -125,6 +126,16 @@ message Event {
|
|||
anytype.model.Account.Config config = 1;
|
||||
anytype.model.Account.Status status = 2;
|
||||
}
|
||||
|
||||
message LinkChallenge {
|
||||
message ClientInfo {
|
||||
string processName = 1;
|
||||
string processPath = 2;
|
||||
bool signatureVerified = 3;
|
||||
}
|
||||
string challenge = 1;
|
||||
ClientInfo clientInfo = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message Object {
|
||||
|
@ -370,6 +381,7 @@ message Event {
|
|||
Name name = 6;
|
||||
Size size = 7;
|
||||
Style style = 8;
|
||||
TargetObjectId targetObjectId = 9;
|
||||
|
||||
message Name {
|
||||
string value = 1;
|
||||
|
@ -403,6 +415,9 @@ message Event {
|
|||
int64 value = 1;
|
||||
}
|
||||
|
||||
message TargetObjectId {
|
||||
string value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,15 +7,15 @@ import "google/protobuf/struct.proto";
|
|||
message SmartBlockSnapshotBase {
|
||||
repeated Block blocks = 1;
|
||||
google.protobuf.Struct details = 2;
|
||||
google.protobuf.Struct fileKeys = 3;
|
||||
// deprecated
|
||||
repeated Relation extraRelations = 4;
|
||||
google.protobuf.Struct fileKeys = 3 [deprecated=true];
|
||||
repeated Relation extraRelations = 4 [deprecated=true];
|
||||
repeated string objectTypes = 5;
|
||||
google.protobuf.Struct collections = 6;
|
||||
repeated string removedCollectionKeys = 8;
|
||||
repeated RelationLink relationLinks = 7;
|
||||
string key = 9; // only used for pb backup purposes, ignored in other cases
|
||||
int64 originalCreatedTimestamp = 10; // ignored in import/export in favor of createdDate relation. Used to store original user-side object creation timestamp
|
||||
FileInfo fileInfo = 11;
|
||||
}
|
||||
|
||||
enum SmartBlockType {
|
||||
|
@ -45,6 +45,8 @@ enum SmartBlockType {
|
|||
|
||||
Identity = 0x214;
|
||||
MissingObject = 0x207;
|
||||
|
||||
FileObject = 0x215;
|
||||
}
|
||||
|
||||
message Block {
|
||||
|
@ -277,6 +279,7 @@ message Block {
|
|||
string mime = 4;
|
||||
int64 size = 5;
|
||||
int64 addedAt = 6;
|
||||
string targetObjectId = 9;
|
||||
|
||||
State state = 7;
|
||||
Style style = 8;
|
||||
|
@ -342,6 +345,7 @@ message Block {
|
|||
Gallery = 2;
|
||||
Kanban = 3;
|
||||
Calendar = 4;
|
||||
Graph = 5;
|
||||
}
|
||||
|
||||
enum Size {
|
||||
|
@ -996,4 +1000,20 @@ message Import {
|
|||
LIMIT_OF_ROWS_OR_RELATIONS_EXCEEDED = 7;
|
||||
FILE_LOAD_ERROR = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message FileEncryptionKey {
|
||||
string path = 1;
|
||||
string key = 2;
|
||||
}
|
||||
|
||||
message FileInfo {
|
||||
string fileId = 1;
|
||||
repeated FileEncryptionKey encryptionKeys = 2;
|
||||
}
|
||||
|
||||
enum ImageKind {
|
||||
Basic = 0;
|
||||
Cover = 1;
|
||||
Icon = 2;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ fun StubFile(
|
|||
id: Id = MockDataFactory.randomUuid(),
|
||||
children: List<Id> = emptyList(),
|
||||
backgroundColor: String? = null,
|
||||
hash: String = MockDataFactory.randomString(),
|
||||
targetObjectId: Id = MockDataFactory.randomString(),
|
||||
name: String = MockDataFactory.randomString(),
|
||||
size: Long = MockDataFactory.randomLong(),
|
||||
type: Block.Content.File.Type? = null,
|
||||
|
@ -105,7 +105,7 @@ fun StubFile(
|
|||
content = Block.Content.File(
|
||||
size = size,
|
||||
name = name,
|
||||
hash = hash,
|
||||
targetObjectId = targetObjectId,
|
||||
type = type,
|
||||
state = state
|
||||
)
|
||||
|
|
|
@ -88,7 +88,7 @@ object MockBlockFactory {
|
|||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
hash = MockDataFactory.randomUuid(),
|
||||
targetObjectId = MockDataFactory.randomUuid(),
|
||||
name = MockDataFactory.randomString(),
|
||||
state = Block.Content.File.State.DONE,
|
||||
mime = MockDataFactory.randomString(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue