Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion app/src/main/java/one/mixin/android/db/ConversationDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ interface ConversationDao : BaseDao<Conversation> {
mu.full_name AS senderFullName,
pu.full_name AS participantFullName, pu.user_id AS participantUserId,
(SELECT count(1) FROM message_mentions me WHERE me.conversation_id = c.conversation_id AND me.has_read = 0) as mentionCount,
mm.mentions AS mentions, ou.membership AS membership
mm.mentions AS mentions, ou.membership AS membership, c.expire_in AS expireIn
FROM conversations c
INNER JOIN users ou ON ou.user_id = c.owner_id
LEFT JOIN messages m ON c.last_message_id = m.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ fun convertToConversationItems(cursor: Cursor?): List<ConversationItem> {
val cursorIndexOfMentionCount = getColumnIndexOrThrow(cursor, "mentionCount")
val cursorIndexOfMentions = getColumnIndexOrThrow(cursor, "mentions")
val cursorIndexOfMembership = getColumnIndexOrThrow(cursor, "membership")
val cursorIndexOfExpireIn = getColumnIndexOrThrow(cursor, "expireIn")
val res = ArrayList<ConversationItem>(cursor.count)
while (cursor.moveToNext()) {
val item: ConversationItem
Expand Down Expand Up @@ -107,6 +108,12 @@ fun convertToConversationItems(cursor: Cursor?): List<ConversationItem> {
}
val tmpMentions = cursor.getString(cursorIndexOfMentions)
val tmpMembership = cursor.getString(cursorIndexOfMembership)
val tmpExpireIn =
if (cursor.isNull(cursorIndexOfExpireIn)) {
null
} else {
cursor.getLong(cursorIndexOfExpireIn)
}
item =
ConversationItem(
tmpConversationId,
Expand Down Expand Up @@ -136,7 +143,8 @@ fun convertToConversationItems(cursor: Cursor?): List<ConversationItem> {
tmpAppId,
tmpMentions,
tmpMentionCount,
membershipConverter.revertData(tmpMembership)
membershipConverter.revertData(tmpMembership),
tmpExpireIn,
)
res.add(item)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class DataProvider {
mu.full_name AS senderFullName,
pu.full_name AS participantFullName, pu.user_id AS participantUserId,
(SELECT count(1) FROM message_mentions me WHERE me.conversation_id = c.conversation_id AND me.has_read = 0) AS mentionCount,
mm.mentions AS mentions, ou.membership AS membership
mm.mentions AS mentions, ou.membership AS membership, c.expire_in AS expireIn
FROM circle_conversations cc
INNER JOIN conversations c ON cc.conversation_id = c.conversation_id
INNER JOIN circles ci ON ci.circle_id = cc.circle_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import one.mixin.android.extension.withArgs
import one.mixin.android.ui.conversation.ConversationViewModel
import one.mixin.android.util.ErrorHandler
import one.mixin.android.util.viewBinding
import one.mixin.android.widget.picker.INTERVAL_DAY
import one.mixin.android.widget.picker.INTERVAL_MONTH
import one.mixin.android.widget.picker.INTERVAL_WEEK
import one.mixin.android.widget.picker.toTimeInterval
import one.mixin.android.widget.picker.toTimeIntervalIndex
import timber.log.Timber
Expand Down Expand Up @@ -53,8 +56,6 @@ class DisappearingFragment : BaseFragment(R.layout.fragment_disappearing) {
disappearingOption1Iv,
disappearingOption2Iv,
disappearingOption3Iv,
disappearingOption4Iv,
disappearingOption5Iv,
disappearingOption6Iv,
)
}
Expand All @@ -67,8 +68,6 @@ class DisappearingFragment : BaseFragment(R.layout.fragment_disappearing) {
disappearingOption1Pb,
disappearingOption2Pb,
disappearingOption3Pb,
disappearingOption4Pb,
disappearingOption5Pb,
disappearingOption6Pb,
)
}
Expand All @@ -77,13 +76,11 @@ class DisappearingFragment : BaseFragment(R.layout.fragment_disappearing) {
private fun Long?.initOption() {
when {
this == null || this <= 0 -> updateOptionCheck(0)
this == 30L -> updateOptionCheck(1)
this == 600L -> updateOptionCheck(2)
this == 7200L -> updateOptionCheck(3)
this == 86400L -> updateOptionCheck(4)
this == 604800L -> updateOptionCheck(5)
this == INTERVAL_DAY -> updateOptionCheck(1)
this == INTERVAL_WEEK -> updateOptionCheck(2)
this == INTERVAL_MONTH -> updateOptionCheck(3)
else -> {
updateOptionCheck(6)
updateOptionCheck(4)
binding.disappearingOption6Interval.text = toTimeInterval(this)
}
}
Expand All @@ -106,30 +103,34 @@ class DisappearingFragment : BaseFragment(R.layout.fragment_disappearing) {
updateUI(0, 0L)
}
disappearingOption1.setOnClickListener {
updateUI(1, 30L)
updateUI(1, INTERVAL_DAY)
}
disappearingOption2.setOnClickListener {
updateUI(2, 600L)
updateUI(2, INTERVAL_WEEK)
}
disappearingOption3.setOnClickListener {
updateUI(3, 7200L)
}
disappearingOption4.setOnClickListener {
updateUI(4, 86400L)
}
disappearingOption5.setOnClickListener {
updateUI(5, 604800L)
updateUI(3, INTERVAL_MONTH)
}

disappearingOption6.setOnClickListener {
DisappearingIntervalBottomFragment.newInstance(timeInterval)
.apply {
onSetCallback {
this@DisappearingFragment.lifecycleScope.launch {
val index = when (it) {
INTERVAL_DAY -> 1
INTERVAL_WEEK -> 2
INTERVAL_MONTH -> 3
else -> 4
}
if (it == timeInterval) {
updateOptionCheck(index)
return@launch
}
disappearingOption6Iv.isVisible = false
disappearingOption6Interval.isVisible = false
disappearingOption6Arrow.isVisible = false
updateUI(6, it)
updateUI(index, it)
disappearingOption6Interval.text = toTimeInterval(it)
Timber.e(
"Set interval ${toTimeInterval(it)} ${
Expand Down Expand Up @@ -203,7 +204,7 @@ class DisappearingFragment : BaseFragment(R.layout.fragment_disappearing) {
for ((i, iv) in checkGroup.withIndex()) {
iv.isVisible = index == i
}
binding.disappearingOption6Arrow.isVisible = index != 6
binding.disappearingOption6Interval.isVisible = index == 6
binding.disappearingOption6Arrow.isVisible = index != 4
binding.disappearingOption6Interval.isVisible = index == 4
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1568,6 +1568,9 @@ class ConversationFragment() :
} else {
renderUser(recipient!!)
}
chatViewModel.observeConversation(conversationId).observe(viewLifecycleOwner) { conversation ->
binding.actionBar.setExpireIconVisible((conversation?.expireIn ?: 0L) > 0L)
}
binding.mentionRv.adapter = mentionAdapter
binding.mentionRv.layoutManager = LinearLayoutManager(context)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ class ConversationViewModel
conversationRepository.getConversation(id)
}

fun observeConversation(id: String) =
conversationRepository.getConversationById(id)

fun findUserById(conversationId: String): LiveData<User> =
userRepository.findUserById(conversationId)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.IdRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.TooltipCompat
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.uber.autodispose.android.autoDispose
Expand All @@ -25,7 +23,6 @@ import one.mixin.android.event.BlinkEvent
import one.mixin.android.extension.CodeType
import one.mixin.android.extension.booleanFromAttribute
import one.mixin.android.extension.dpToPx
import one.mixin.android.extension.fullTime
import one.mixin.android.extension.getColorCode
import one.mixin.android.session.Session
import one.mixin.android.util.GsonHelper
Expand Down Expand Up @@ -159,27 +156,12 @@ abstract class BaseViewHolder constructor(containerView: View) :

fun chatJumpLayout(
chatJump: ImageView,
isMe: Boolean,
expireIn: Long?,
expireAt: Long?,
@IdRes id: Int,
@Suppress("UNUSED_PARAMETER") isMe: Boolean,
@Suppress("UNUSED_PARAMETER") expireIn: Long?,
@Suppress("UNUSED_PARAMETER") expireAt: Long?,
@Suppress("UNUSED_PARAMETER") @IdRes id: Int,
) {
chatJump.isVisible = expireIn != null
if (expireIn != null) {
chatJump.setImageResource(R.drawable.ic_expire_message)
expireAt?.fullTime()?.let {
TooltipCompat.setTooltipText(chatJump, chatJump.context.getString(R.string.Expired_tip, it))
}
(chatJump.layoutParams as ConstraintLayout.LayoutParams).apply {
if (isMe) {
endToStart = id
startToEnd = View.NO_ID
} else {
endToStart = View.NO_ID
startToEnd = id
}
}
}
chatJump.isVisible = false
}

private val argbEvaluator: ArgbEvaluator by lazy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ class ConversationListFragment : LinkFragment() {
val id = Session.getAccountId()
binding.nameTv.setName(conversationItem)
binding.groupNameTv.visibility = GONE
binding.msgExpire.isVisible = conversationItem.isExpire()
binding.msgExpire.isVisible = conversationItem.isDisappearingEnabled()
binding.mentionFlag.isVisible =
conversationItem.mentionCount != null && conversationItem.mentionCount > 0
when {
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/one/mixin/android/vo/ConversationItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ data class ConversationItem(
val appId: String?,
val mentions: String?,
val mentionCount: Int?,
val membership: Membership?
val membership: Membership?,
val expireIn: Long? = null,
) : ICategory, IConversationCategory {
companion object {
val DIFF_CALLBACK =
Expand Down Expand Up @@ -87,6 +88,8 @@ data class ConversationItem(

fun isExpire() = actionName == SystemConversationAction.EXPIRE.name

fun isDisappearingEnabled() = (expireIn ?: 0L) > 0L

fun isBot(): Boolean {
return isContactConversation() && ownerIdentityNumber.isBotIdentityNumber()
}
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/one/mixin/android/widget/TitleView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class TitleView(context: Context, attrs: AttributeSet) : RelativeLayout(context,
ViewTitleBinding.inflate(LayoutInflater.from(context), this, true)

val titleTv = binding.titleTv
val expireIv = binding.expireIv
val leftIb = binding.leftIb
val rightIb = binding.rightIb
val rightTv = binding.rightTv
Expand Down Expand Up @@ -204,6 +205,10 @@ class TitleView(context: Context, attrs: AttributeSet) : RelativeLayout(context,
}
}

fun setExpireIconVisible(visible: Boolean) {
binding.expireIv.isVisible = visible
}

fun setUser(user: User, onClickListener: OnClickListener) {
binding.titleTv.setName(user)
binding.titleTv.setOnIconClickListener(onClickListener)
Expand Down
78 changes: 57 additions & 21 deletions app/src/main/java/one/mixin/android/widget/picker/TimeInterval.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,63 @@ import android.content.res.Resources
import one.mixin.android.MixinApplication
import one.mixin.android.R

const val INTERVAL_SECOND = 1L
const val INTERVAL_MINUTE = 60L
const val INTERVAL_HOUR = 3_600L
const val INTERVAL_DAY = 86_400L
const val INTERVAL_WEEK = 604_800L
const val INTERVAL_MONTH = 2_592_000L
const val INTERVAL_YEAR = 31_536_000L

val timeIntervalUnits by lazy {
listOf(
R.plurals.time_interval_unit_day,
R.plurals.time_interval_unit_week,
R.plurals.time_interval_unit_month,
R.plurals.time_interval_unit_year,
)
}

private val displayTimeIntervalUnits by lazy {
listOf(
R.plurals.time_interval_unit_second,
R.plurals.time_interval_unit_minute,
R.plurals.time_interval_unit_hour,
R.plurals.time_interval_unit_day,
R.plurals.time_interval_unit_week,
R.plurals.time_interval_unit_month,
R.plurals.time_interval_unit_year,
)
}

private val pickerIntervals = listOf(INTERVAL_DAY, INTERVAL_WEEK, INTERVAL_MONTH, INTERVAL_YEAR)

private fun timeString(
resources: Resources,
count: Long,
index: Int,
unitRes: Int,
) =
resources.getQuantityString(
timeIntervalUnits[index],
unitRes,
count.toInt(),
)

private fun intervalString(
resources: Resources,
interval: Long,
unit: Long,
index: Int,
unitRes: Int,
): String {
val count = interval / unit
return "$count ${timeString(resources, count, index)}"
return "$count ${timeString(resources, count, unitRes)}"
}

val numberList by lazy {
listOf(
(1..59).map { it.toString() }.toList(),
(1..59).map { it.toString() }.toList(),
(1..23).map { it.toString() }.toList(),
(1..6).map { it.toString() }.toList(),
(1..12).map { it.toString() }.toList(),
(1..6).map { it.toString() },
(1..3).map { it.toString() },
(1..6).map { it.toString() },
listOf("1"),
)
}

Expand All @@ -49,24 +69,40 @@ internal fun toTimeInterval(
interval: Long,
): String =
when {
interval < 60L -> intervalString(resources, interval, 1L, 0)
interval < 3600L -> intervalString(resources, interval, 60L, 1)
interval < 86400L -> intervalString(resources, interval, 3600L, 2)
interval < 604800L -> intervalString(resources, interval, 86400L, 3)
else -> intervalString(resources, interval, 604800L, 4)
interval > 0 && interval % INTERVAL_YEAR == 0L ->
intervalString(resources, interval, INTERVAL_YEAR, displayTimeIntervalUnits[6])
interval >= INTERVAL_MONTH && interval % INTERVAL_MONTH == 0L ->
intervalString(resources, interval, INTERVAL_MONTH, displayTimeIntervalUnits[5])
interval >= INTERVAL_WEEK && interval % INTERVAL_WEEK == 0L ->
intervalString(resources, interval, INTERVAL_WEEK, displayTimeIntervalUnits[4])
interval >= INTERVAL_DAY && interval % INTERVAL_DAY == 0L ->
intervalString(resources, interval, INTERVAL_DAY, displayTimeIntervalUnits[3])
interval >= INTERVAL_HOUR && interval % INTERVAL_HOUR == 0L ->
intervalString(resources, interval, INTERVAL_HOUR, displayTimeIntervalUnits[2])
interval >= INTERVAL_MINUTE && interval % INTERVAL_MINUTE == 0L ->
intervalString(resources, interval, INTERVAL_MINUTE, displayTimeIntervalUnits[1])
else ->
intervalString(resources, interval, INTERVAL_SECOND, displayTimeIntervalUnits[0])
}

fun toTimeInterval(interval: Long): String =
toTimeInterval(MixinApplication.get().resources, interval)

fun toTimeIntervalIndex(interval: Long): Pair<Int, Int> =
when {
interval < 60L -> Pair(0, (interval / 1L).toInt() - 1)
interval < 3600L -> Pair(1, (interval / 60L).toInt() - 1)
interval < 86400L -> Pair(2, (interval / 3600L).toInt() - 1)
interval < 604800L -> Pair(3, (interval / 86400L).toInt() - 1)
else -> Pair(4, (interval / 604800L).toInt() - 1)
fun toTimeIntervalIndex(interval: Long): Pair<Int, Int> {
pickerIntervals.forEachIndexed { index, unit ->
if (interval >= unit && interval % unit == 0L) {
val count = (interval / unit).toInt()
val max = numberList[index].size
if (count in 1..max) {
return Pair(index, count - 1)
}
}
}
return Pair(0, 0)
}

fun pickerIntervalSeconds(unitIndex: Int): Long =
pickerIntervals.getOrElse(unitIndex) { INTERVAL_DAY }

fun Long?.getTimeInterval(): String {
return when {
Expand Down
Loading