Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • circles/circles-android
1 result
Show changes
Commits on Source (6)
Showing
with 291 additions and 89 deletions
......@@ -137,6 +137,10 @@ class DMTimelineDialogFragment :
withConfirmation(RemovePost()) { viewModel.removeMessage(args.roomId, eventId) }
}
override fun onEditActionClicked(eventId: String, message: String) {
binding.vSendMessage.setTextForEdit(eventId, message)
}
override fun onSaveToDevice(content: PostContent) {
viewModel.saveToDevice(content)
}
......
......@@ -13,6 +13,6 @@ interface DmOptionsListener {
fun onEmojiChipClicked(eventId: String, emoji: String, isUnSend: Boolean)
fun onSaveToDevice(content: PostContent)
fun onRemove(eventId: String)
fun onEdit(eventId: String)
fun onEditActionClicked(eventId: String, message: String)
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.futo.circles.core.base.fragment.TransparentBackgroundBottomSheetDialogFragment
import org.futo.circles.core.extensions.navigateSafe
import org.futo.circles.core.extensions.setIsVisible
import org.futo.circles.core.model.TextContent
import org.futo.circles.core.provider.PreferencesProvider
import org.futo.circles.databinding.BottomSheetDmMenuBinding
import org.futo.circles.feature.direct.timeline.listeners.DmOptionsListener
......@@ -57,10 +58,14 @@ class DmMenuBottomSheet : TransparentBackgroundBottomSheetDialogFragment() {
}
}
tvEdit.apply {
setIsVisible(viewModel.isMyPost())
setIsVisible(
viewModel.isMyPost() && viewModel.getPostContent()?.isText() == true
)
setOnClickListener {
menuListener?.onEdit(args.eventId)
dismiss()
(viewModel.getPostContent() as? TextContent)?.let {
menuListener?.onEditActionClicked(args.eventId, it.message)
dismiss()
}
}
}
tvSaveToDevice.apply {
......
package org.futo.circles.view
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.ReactionsData
import org.futo.circles.databinding.ViewDmFooterBinding
import org.futo.circles.feature.timeline.list.PostOptionsListener
class DmFooterView(
context: Context,
attrs: AttributeSet? = null,
) : ConstraintLayout(context, attrs) {
private val binding =
ViewDmFooterBinding.inflate(LayoutInflater.from(context), this)
private var optionsListener: PostOptionsListener? = null
private var post: Post? = null
fun setData(data: Post, isThread: Boolean) {
post = data
bindReactionsList(data.reactionsData)
}
fun bindPayload(reactions: List<ReactionsData>, isEdited: Boolean, time: Long) {
post = post?.copy(
postInfo = post!!.postInfo.copy(isEdited = isEdited, timestamp = time),
reactionsData = reactions
)
bindReactionsList(reactions)
}
private fun bindReactionsList(reactions: List<ReactionsData>) {
binding.vEmojisList.bindReactionsList(
reactions,
true,
object : ReactionChipClickListener {
override fun onReactionChipClicked(emoji: String, isAddedByMe: Boolean) {
post?.let {
optionsListener?.onEmojiChipClicked(
it.postInfo.roomId,
it.id,
emoji,
isAddedByMe
)
}
}
})
}
fun addEmojiFromPickerLocalUpdate(emoji: String) {
binding.vEmojisList.addEmojiFromPickerLocalUpdate(emoji)
}
}
\ No newline at end of file
package org.futo.circles.view
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.HorizontalScrollView
import androidx.core.view.children
import org.futo.circles.core.base.NetworkObserver
import org.futo.circles.core.extensions.setIsVisible
import org.futo.circles.core.model.ReactionsData
import org.futo.circles.databinding.ViewEmijiListBinding
interface ReactionChipClickListener {
fun onReactionChipClicked(emoji: String, isAddedByMe: Boolean)
}
class EmojiListView(
context: Context,
attrs: AttributeSet? = null,
) : HorizontalScrollView(context, attrs) {
private val binding =
ViewEmijiListBinding.inflate(LayoutInflater.from(context), this)
private var reactionChipClickListener: ReactionChipClickListener? = null
private var isUserAbleToPost: Boolean = true
fun bindReactionsList(
reactionsData: List<ReactionsData>,
isUserAbleToPost: Boolean,
reactionChipClickedCallback: ReactionChipClickListener
) {
this.isUserAbleToPost = isUserAbleToPost
this.reactionChipClickListener = reactionChipClickedCallback
this.setIsVisible(reactionsData.isNotEmpty())
binding.lEmojisContainer.removeAllViews()
reactionsData.forEach { addReactionItem(it) }
}
private fun addReactionItem(reactionsData: ReactionsData) {
binding.lEmojisContainer.addView(ReactionItemView(context).apply {
setup(reactionsData) { reaction ->
locallyUpdateEmojisList(this, reaction)
reactionChipClickListener?.onReactionChipClicked(
reaction.key,
reaction.addedByMe
)
}
})
}
private fun locallyUpdateEmojisList(view: ReactionItemView, reaction: ReactionsData) {
if (!NetworkObserver.isConnected()) return
if (!isUserAbleToPost) return
if (reaction.addedByMe) {
if (reaction.count == 1) {
binding.lEmojisContainer.removeView(view)
if (binding.lEmojisContainer.children.count() == 0)
this.setIsVisible(false)
} else view.bindReactionData(
reaction.copy(
addedByMe = false,
count = reaction.count - 1
)
)
} else {
view.bindReactionData(reaction.copy(addedByMe = true, count = reaction.count + 1))
}
}
fun addEmojiFromPickerLocalUpdate(emoji: String) {
val view = binding.lEmojisContainer.findViewWithTag<ReactionItemView>(emoji)
view?.let {
val data = it.reactionsData ?: return
it.bindReactionData(data.copy(count = data.count + 1, addedByMe = true))
} ?: kotlin.run {
this.setIsVisible(true)
addReactionItem(ReactionsData(emoji, 1, true))
}
}
}
\ No newline at end of file
......@@ -4,12 +4,9 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.children
import androidx.core.view.isVisible
import com.vanniktech.ui.parentViewGroup
import org.futo.circles.core.base.NetworkObserver
import org.futo.circles.core.extensions.getCurrentUserPowerLevel
import org.futo.circles.core.extensions.setIsVisible
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.ReactionsData
import org.futo.circles.databinding.ViewPostFooterBinding
......@@ -87,55 +84,25 @@ class PostFooterView(
}
private fun bindReactionsList(reactions: List<ReactionsData>) {
binding.hsEmojis.setIsVisible(reactions.isNotEmpty())
binding.lEmojisContainer.removeAllViews()
reactions.forEach { addReactionItem(it) }
}
private fun addReactionItem(reactionsData: ReactionsData) {
binding.lEmojisContainer.addView(ReactionItemView(context).apply {
setup(reactionsData) { reaction ->
locallyUpdateEmojisList(this, reaction)
post?.let {
optionsListener?.onEmojiChipClicked(
it.postInfo.roomId,
it.id,
reaction.key,
reaction.addedByMe
)
binding.vEmojisList.bindReactionsList(
reactions,
isAbleToPost(),
object : ReactionChipClickListener {
override fun onReactionChipClicked(emoji: String, isAddedByMe: Boolean) {
post?.let {
optionsListener?.onEmojiChipClicked(
it.postInfo.roomId,
it.id,
emoji,
isAddedByMe
)
}
}
}
})
}
private fun locallyUpdateEmojisList(view: ReactionItemView, reaction: ReactionsData) {
if (!NetworkObserver.isConnected()) return
if (!isAbleToPost()) return
if (reaction.addedByMe) {
if (reaction.count == 1) {
binding.lEmojisContainer.removeView(view)
if (binding.lEmojisContainer.children.count() == 0)
binding.hsEmojis.setIsVisible(false)
} else view.bindReactionData(
reaction.copy(
addedByMe = false,
count = reaction.count - 1
)
)
} else {
view.bindReactionData(reaction.copy(addedByMe = true, count = reaction.count + 1))
}
})
}
fun addEmojiFromPickerLocalUpdate(emoji: String) {
val view = binding.lEmojisContainer.findViewWithTag<ReactionItemView>(emoji)
view?.let {
val data = it.reactionsData ?: return
it.bindReactionData(data.copy(count = data.count + 1, addedByMe = true))
} ?: kotlin.run {
binding.hsEmojis.setIsVisible(true)
addReactionItem(ReactionsData(emoji, 1, true))
}
binding.vEmojisList.addEmojiFromPickerLocalUpdate(emoji)
}
private fun isAbleToPost() =
......
......@@ -7,7 +7,6 @@ import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.widget.doAfterTextChanged
import org.futo.circles.R
import org.futo.circles.core.extensions.getText
import org.futo.circles.core.extensions.setIsVisible
import org.futo.circles.databinding.ViewSendMessageBinding
......@@ -54,4 +53,8 @@ class SendMessageView(
binding.etMessage.setSelection(selection + unicode.length)
}
fun setTextForEdit(eventId: String, message: String) {
binding.etMessage.setText(message)
}
}
\ No newline at end of file
......@@ -24,7 +24,6 @@
android:id="@+id/ivMediaContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/media_post_background"
android:foreground="?attr/selectableItemBackground"
android:padding="8dp"
android:scaleType="fitCenter"
......
......@@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginStart="36dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp">
......@@ -14,33 +15,47 @@
android:layout_height="0dp"
android:background="@color/chip_selected_color"
app:layout_constraintBottom_toBottomOf="@id/tvTime"
app:layout_constraintEnd_toEndOf="@id/tvMessage"
app:layout_constraintStart_toStartOf="@id/tvMessage"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/messageBarrier"
app:layout_constraintTop_toTopOf="@id/tvMessage"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Message.My" />
<TextView
android:id="@+id/tvMessage"
style="@style/body"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="web"
android:padding="8dp"
android:paddingHorizontal="12dp"
android:paddingVertical="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="@id/ivBackground"
app:layout_constraintTop_toTopOf="parent"
tools:text="sadasdasdasdasdasdasdasdasdasd" />
tools:text="Some long message" />
<TextView
android:id="@+id/tvTime"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="end"
android:lines="1"
android:paddingHorizontal="12dp"
android:paddingBottom="4dp"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvMessage"
tools:text="sadasdasdasdasdasdasdasdasdasd" />
tools:text="Jul 17, 6:00 PM" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/messageBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="start"
app:constraint_referenced_ids="tvMessage, tvTime"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -23,7 +23,6 @@
android:id="@+id/ivMediaContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/media_post_background"
android:foreground="?attr/selectableItemBackground"
android:padding="8dp"
android:scaleType="fitCenter"
......
......@@ -2,8 +2,9 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="36dp">
......@@ -14,33 +15,46 @@
android:layout_height="0dp"
android:background="@color/post_card_background_color"
app:layout_constraintBottom_toBottomOf="@id/tvTime"
app:layout_constraintEnd_toEndOf="@id/tvMessage"
app:layout_constraintStart_toStartOf="@id/tvMessage"
app:layout_constraintEnd_toEndOf="@id/messageBarrier"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/tvMessage"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Message.Other" />
<TextView
android:id="@+id/tvMessage"
style="@style/body"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="web"
android:padding="8dp"
app:layout_constraintEnd_toEndOf="parent"
android:padding="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="sadasdasdasdasdasdasdasdasdasd" />
tools:text="Some long message" />
<TextView
android:id="@+id/tvTime"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="end"
android:lines="1"
android:paddingHorizontal="12dp"
android:paddingBottom="4dp"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvMessage"
tools:text="sadasdasdasdasdasdasdasdasdasd" />
tools:text="Jul 17, 6:00 PM" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/messageBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="tvMessage, tvTime"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<org.futo.circles.view.EmojiListView
android:id="@+id/vEmojisList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tvTime"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:lines="1"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tvEditedLabel"
tools:text="Jul 17, 6:00 PM" />
<TextView
android:id="@+id/tvEditedLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:paddingStart="4dp"
android:paddingEnd="0dp"
android:text="@string/edited_label"
android:textSize="12sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:visibility="visible" />
</merge>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:parentTag="android.widget.HorizontalScrollView">
<LinearLayout
android:id="@+id/lEmojisContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" />
</merge>
\ No newline at end of file
......@@ -7,27 +7,16 @@
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<HorizontalScrollView
android:id="@+id/hsEmojis"
<org.futo.circles.view.EmojiListView
android:id="@+id/vEmojisList"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="@id/btnLike"
app:layout_constraintEnd_toStartOf="@id/btnLike"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/btnLike"
tools:visibility="visible">
<LinearLayout
android:id="@+id/lEmojisContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" />
</HorizontalScrollView>
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnLike"
......@@ -47,7 +36,7 @@
app:iconTint="@color/button_src_state_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btnReply"
app:layout_constraintStart_toEndOf="@id/hsEmojis"
app:layout_constraintStart_toEndOf="@id/vEmojisList"
app:layout_constraintTop_toBottomOf="@id/divider"
app:tint="@color/button_src_state_color" />
......
......@@ -6,6 +6,8 @@ sealed class PostContent(open val type: PostContentType) {
type == PostContentType.IMAGE_CONTENT || type == PostContentType.VIDEO_CONTENT
fun isPoll(): Boolean = type == PostContentType.POLL_CONTENT
fun isText(): Boolean = type == PostContentType.TEXT_CONTENT
}
......