1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-3263 Working code

This commit is contained in:
nvgurova 2025-01-23 14:17:58 +01:00
parent c4f40d15c4
commit a96ebb9aea
No known key found for this signature in database
GPG key ID: 3283F7371DE9C0D2
13 changed files with 199 additions and 49 deletions

View file

@ -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,

View file

@ -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) {
@ -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) {
@ -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) {

View file

@ -0,0 +1,56 @@
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 {
val imageWidth = toTransform.width
val imageHeight = toTransform.height
val targetAspectRatio = maxWidth.toFloat() / maxHeight
return 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
}
}
override fun equals(other: Any?) = other is CustomImageResizeTransformation
override fun hashCode() = "CustomImageResizeTransformation".hashCode()
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
messageDigest.update("CustomImageResizeTransformation".toByteArray())
}
}

View file

@ -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
@ -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 {
@ -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)
@ -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(
@ -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() }
@ -299,9 +331,11 @@ 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()
@ -309,9 +343,11 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
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()
@ -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
@ -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)
@ -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
@ -576,7 +617,8 @@ sealed class Title(view: View) : BlockViewHolder(view), TextHolder {
) {
super.bind(
item = item,
onCoverClicked = {}
onCoverClicked = {},
click = {}
)
icon.setIcon(item.icon)
}

View file

@ -392,4 +392,4 @@ class ObjectIconWidget @JvmOverloads constructor(
this.width = emojiSize
}
}
}
}

View file

@ -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"
@ -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"

View file

@ -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"

View file

@ -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>

View file

@ -47,6 +47,11 @@ interface UserSettingsCache {
suspend fun getAllContentSort(space: SpaceId): Pair<Id, Boolean>?
suspend fun setAllContentSort(space: SpaceId, sort: Id, isAsc: Boolean)
suspend fun setTooltipShown(shown: Boolean)
suspend fun isTooltipShown(): Boolean
suspend fun setSpaceSwitchCount(count: Int)
suspend fun getSpaceSwitchCount(): Int
suspend fun setRelativeDates(account: Account, enabled: Boolean)
suspend fun setDateFormat(account: Account, format: String)

View file

@ -570,6 +570,22 @@ class DefaultUserSettingsCache(
}
}
override suspend fun setTooltipShown(shown: Boolean) {
prefs.edit().putBoolean(TOOLTIP_SHOWN_KEY, shown).apply()
}
override suspend fun isTooltipShown(): Boolean {
return prefs.getBoolean(TOOLTIP_SHOWN_KEY, false)
}
override suspend fun setSpaceSwitchCount(count: Int) {
prefs.edit().putInt(SPACE_SWITCH_COUNT_KEY, count).apply()
}
override suspend fun getSpaceSwitchCount(): Int {
return prefs.getInt(SPACE_SWITCH_COUNT_KEY, 0)
}
companion object {
const val CURRENT_SPACE_KEY = "prefs.user_settings.current_space"
const val DEFAULT_OBJECT_TYPE_ID_KEY = "prefs.user_settings.default_object_type.id"
@ -585,5 +601,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"
}
}

View file

@ -3843,6 +3843,25 @@ class EditorViewModel(
else -> Unit
}
}
is ListenerType.Picture.TitleView -> {
when (mode) {
EditorMode.Edit, EditorMode.Locked, EditorMode.Read -> {
if (!clicked.item.image.isNullOrEmpty()){
dispatch(
Command.OpenFullScreenImage(
target = "",
url = clicked.item.image
)
)
} else {
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.item.id)
else -> Unit
}
}
is ListenerType.Picture.View -> {
when (mode) {
EditorMode.Edit, EditorMode.Locked, EditorMode.Read -> {

View file

@ -23,6 +23,7 @@ sealed interface ListenerType {
}
sealed class Picture: ListenerType {
data class TitleView(val item: BlockView.Title.Basic) : Picture()
data class View(val target: String) : Picture()
data class Placeholder(val target: String) : Picture()
data class Upload(val target: String) : Picture()

View file

@ -1516,7 +1516,7 @@ class DefaultBlockViewRenderer @Inject constructor(
text = fieldParser.getObjectName(currentObject),
image = currentObject.iconImage?.let { image ->
if (image.isNotBlank())
urlBuilder.thumbnail(image)
urlBuilder.original(image)
else
null
},