Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DROID-3264 Editor | Enhancement | Improved image file layout and features #2045

Merged
merged 4 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -824,29 +824,28 @@ open class ObjectSetFragment :
.launchIn(lifecycleScope)
}

binding.objectHeader.root.findViewById<View>(R.id.imageIcon).apply {
if (header.title.image != null) visible() else gone()
binding.objectHeader.root.findViewById<ImageView>(R.id.imageIcon).apply {
jobs += this.clicks()
.throttleFirst()
.onEach { vm.onObjectIconClicked() }
.launchIn(lifecycleScope)

if (header.title.image != null) {
this.visible()
Glide
.with(this)
.load(header.title.image)
.centerCrop()
.into(this)
} else {
this.gone()
this.setImageDrawable(null)
}
}

binding.objectHeader.root.findViewById<ImageView>(R.id.emojiIcon)
.setEmojiOrNull(header.title.emoji)

if (header.title.image != null) {
binding.objectHeader.root.findViewById<ImageView>(R.id.imageIcon).apply {
Glide
.with(this)
.load(header.title.image)
.centerCrop()
.into(this)
}
} else {
binding.objectHeader.root.findViewById<ImageView>(R.id.imageIcon).setImageDrawable(null)
}

setCover(
coverColor = header.title.coverColor,
coverGradient = header.title.coverGradient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,8 @@ class BlockAdapter(
bind(
item = blocks[position] as BlockView.Title.Basic,
onPageIconClicked = onPageIconClicked,
onCoverClicked = onCoverClicked
onCoverClicked = onCoverClicked,
click = onClickListener
)
setTextInputClickListener {
if (Build.VERSION.SDK_INT == N || Build.VERSION.SDK_INT == N_MR1) {
Expand All @@ -1356,7 +1357,8 @@ class BlockAdapter(
bind(
item = blocks[position] as BlockView.Title.Todo,
onPageIconClicked = onPageIconClicked,
onCoverClicked = onCoverClicked
onCoverClicked = onCoverClicked,
click = onClickListener
)
setTextInputClickListener {
if (Build.VERSION.SDK_INT == N || Build.VERSION.SDK_INT == N_MR1) {
Expand All @@ -1373,7 +1375,8 @@ class BlockAdapter(
bind(
item = blocks[position] as BlockView.Title.Profile,
onProfileIconClicked = onClickListener,
onCoverClicked = onCoverClicked
onCoverClicked = onCoverClicked,
click = onClickListener
)
setTextInputClickListener {
if (Build.VERSION.SDK_INT == N || Build.VERSION.SDK_INT == N_MR1) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.anytypeio.anytype.core_ui.features.editor.holders.other

import android.graphics.Bitmap
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import java.security.MessageDigest

class CustomImageResizeTransformation(
private val maxWidth: Int,
private val maxHeight: Int
) : BitmapTransformation() {

override fun transform(
pool: BitmapPool,
toTransform: Bitmap,
outWidth: Int,
outHeight: Int
): Bitmap {
return try {
val imageWidth = toTransform.width
val imageHeight = toTransform.height
val targetAspectRatio = maxWidth.toFloat() / maxHeight

when {
imageWidth > maxWidth && imageHeight > maxHeight -> {
val imageAspectRatio = imageWidth.toFloat() / imageHeight

if (imageAspectRatio > targetAspectRatio) {
val cropWidth = (imageHeight * targetAspectRatio).toInt()
val cropStartX = (imageWidth - cropWidth) / 2
Bitmap.createBitmap(toTransform, cropStartX, 0, cropWidth, imageHeight)
} else {
val cropHeight = (imageWidth / targetAspectRatio).toInt()
val cropStartY = (imageHeight - cropHeight) / 2
Bitmap.createBitmap(toTransform, 0, cropStartY, imageWidth, cropHeight)
}
}
imageWidth > maxWidth && imageHeight <= maxHeight -> {
val scaleFactor = maxWidth.toFloat() / imageWidth
val newHeight = (imageHeight * scaleFactor).toInt()
Bitmap.createScaledBitmap(toTransform, maxWidth, newHeight, true)
}
imageHeight > maxHeight && imageWidth <= maxWidth -> {
val cropHeight = (imageWidth / targetAspectRatio).toInt()
val cropStartY = (imageHeight - cropHeight) / 2
Bitmap.createBitmap(toTransform, 0, cropStartY, imageWidth, cropHeight)
}
else -> toTransform
}
} catch (e: Exception) {
e.printStackTrace()
toTransform
}
}

override fun equals(other: Any?) = other is CustomImageResizeTransformation
override fun hashCode() = "CustomImageResizeTransformation".hashCode()
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
messageDigest.update("CustomImageResizeTransformation".toByteArray())
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.anytypeio.anytype.core_ui.features.editor.holders.other

import android.content.Context
import android.graphics.Bitmap
import android.text.Spannable
import android.util.TypedValue
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout.LayoutParams
Expand Down Expand Up @@ -38,6 +41,11 @@ import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import java.security.MessageDigest
import timber.log.Timber

sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
Expand All @@ -50,7 +58,8 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {

fun bind(
item: BlockView.Title,
onCoverClicked: () -> Unit
onCoverClicked: () -> Unit,
click: (ListenerType) -> Unit
) {
setImage(item)
applyTextColor(item)
Expand Down Expand Up @@ -162,22 +171,34 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
}
}
}

open fun setImage(item: BlockView.Title) {
Timber.d("Setting image for ${item.id}, image=${item.image}")
item.image?.let { url ->
image.visible()
Glide
.with(image)
.load(url)
.centerCrop()
.into(image)
} ?: apply { image.setImageDrawable(null) }
loadImageWithCustomResize(image, url)
} ?: run { image.setImageDrawable(null) }
}

private fun showKeyboard() {
content.postDelayed(16L) {
imm().showSoftInput(content, InputMethodManager.SHOW_IMPLICIT)
}
private fun loadImageWithCustomResize(imageView: ImageView, url: String) {
val context = imageView.context
val displayMetrics = context.resources.displayMetrics
val screenWidth = displayMetrics.widthPixels
val maxWidth = screenWidth - dpToPx(context, 40)
val maxHeight = dpToPx(context, 443)

Glide.with(context)
.load(url)
.override(Target.SIZE_ORIGINAL)
.apply(RequestOptions().transform(CustomImageResizeTransformation(maxWidth, maxHeight)))
.into(imageView)
}

private fun dpToPx(context: Context, dp: Int): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
context.resources.displayMetrics
).toInt()
}

open fun processPayloads(
Expand Down Expand Up @@ -275,14 +296,25 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
fun bind(
item: BlockView.Title.Basic,
onPageIconClicked: () -> Unit,
onCoverClicked: () -> Unit
onCoverClicked: () -> Unit,
click: (ListenerType) -> Unit
) {
super.bind(
item = item,
onCoverClicked = onCoverClicked
onCoverClicked = onCoverClicked,
click = click
)
setEmoji(item)
applySearchHighlights(item)

image.setOnClickListener {
click(
ListenerType.Picture.TitleView(
item = item
)
)
}

if (item.mode == BlockView.Mode.EDIT) {
icon.setOnClickListener { onPageIconClicked() }
image.setOnClickListener { onPageIconClicked() }
Expand All @@ -299,19 +331,23 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
topMargin = dimen(R.dimen.dp_10)
}
binding.imageIcon.updateLayoutParams<ConstraintLayout.LayoutParams> {
topMargin = if (!item.hasCover) dimen(R.dimen.dp_51) else dimen(R.dimen.dp_102)
topMargin =
if (!item.hasCover) dimen(R.dimen.dp_51) else dimen(R.dimen.dp_102)
}
}

item.emoji != null -> {
binding.imageIcon.gone()
binding.docEmojiIconContainer.visible()
binding.title.updateLayoutParams<ConstraintLayout.LayoutParams> {
topMargin = dimen(R.dimen.dp_12)
}
binding.docEmojiIconContainer.updateLayoutParams<ConstraintLayout.LayoutParams> {
topMargin = if (!item.hasCover) dimen(R.dimen.dp_60) else dimen(R.dimen.dp_120)
topMargin =
if (!item.hasCover) dimen(R.dimen.dp_60) else dimen(R.dimen.dp_120)
}
}

else -> {
binding.imageIcon.gone()
binding.docEmojiIconContainer.gone()
Expand Down Expand Up @@ -397,9 +433,10 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
override val content: TextInputWidget = binding.title
override val selectionView: View = itemView

private val gradientView : ComposeView get() = binding
.docProfileIconContainer
.findViewById(R.id.gradient)
private val gradientView: ComposeView
get() = binding
.docProfileIconContainer
.findViewById(R.id.gradient)

private val iconText = binding.imageText
private var hasImage = false
Expand All @@ -411,11 +448,13 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
fun bind(
item: BlockView.Title.Profile,
onProfileIconClicked: (ListenerType) -> Unit,
onCoverClicked: () -> Unit
onCoverClicked: () -> Unit,
click: (ListenerType) -> Unit
) {
super.bind(
item = item,
onCoverClicked = onCoverClicked
onCoverClicked = onCoverClicked,
click = click
)
setupMargins(item)
applySearchHighlights(item)
Expand Down Expand Up @@ -512,11 +551,13 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
fun bind(
item: BlockView.Title.Todo,
onPageIconClicked: () -> Unit,
onCoverClicked: () -> Unit
onCoverClicked: () -> Unit,
click: (ListenerType) -> Unit
) {
super.bind(
item = item,
onCoverClicked = onCoverClicked
onCoverClicked = onCoverClicked,
click = click
)
setLocked(item.mode)
checkbox.isSelected = item.isChecked
Expand Down Expand Up @@ -576,7 +617,8 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
) {
super.bind(
item = item,
onCoverClicked = {}
onCoverClicked = {},
click = {}
)
icon.setIcon(item.icon)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,4 +392,4 @@ class ObjectIconWidget @JvmOverloads constructor(
this.width = emojiSize
}
}
}
}
15 changes: 9 additions & 6 deletions core-ui/src/main/res/layout/item_block_title.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,24 @@

<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageIcon"
android:layout_width="108dp"
android:layout_height="108dp"
tools:src="@drawable/a123"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="443dp"
android:layout_gravity="bottom"
android:layout_marginStart="15dp"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:layout_marginTop="51dp"
android:adjustViewBounds="true"
android:background="@color/shape_tertiary"
android:padding="4dp"
android:transitionName="@string/logo_transition"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:shapeAppearance="@style/TitleImageAppearanceOverlay"
app:strokeColor="@color/background_primary"
app:strokeWidth="4dp"
tools:visibility="gone" />
tools:visibility="visible" />

<com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
android:id="@+id/title"
Expand All @@ -76,7 +79,7 @@
android:paddingStart="20dp"
android:paddingEnd="20dp"
app:ignoreDragAndDrop="true"
android:layout_marginTop="@dimen/dp_32"
android:layout_marginTop="@dimen/dp_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier"
Expand Down
2 changes: 2 additions & 0 deletions core-ui/src/main/res/layout/item_block_title_file.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
android:layout_marginStart="28dp"
android:layout_marginTop="80dp"
app:imageSize="80dp"
android:clickable="true"
android:focusable="true"
tools:src="@drawable/ic_mime_pdf"
android:background="@drawable/bg_title_file_icon"
android:transitionName="@string/logo_transition"
Expand Down
1 change: 1 addition & 0 deletions core-ui/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<dimen name="dp_102">102dp</dimen>
<dimen name="dp_120">120dp</dimen>
<dimen name="dp_203">203dp</dimen>
<dimen name="dp_443">443dp</dimen>

<dimen name="roundedTextBorderRadius">4dp</dimen>
<dimen name="roundedTextBorderWidth">1dp</dimen>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,5 +585,8 @@ class DefaultUserSettingsCache(

const val COLLAPSED_WIDGETS_KEY = "prefs.user_settings.collapsed-widgets"
const val ACTIVE_WIDGETS_VIEWS_KEY = "prefs.user_settings.active-widget-views"

const val TOOLTIP_SHOWN_KEY = "tooltip_shown_key"
const val SPACE_SWITCH_COUNT_KEY = "space_switch_count_key"
}
}
Loading