1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-17 04:00:48 +01:00

supported disable_notifications message

This commit is contained in:
Mariotaku Lee 2017-02-21 17:19:02 +08:00
parent 81bf409cca
commit 6de24eff0c
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
9 changed files with 88 additions and 129 deletions

View File

@ -137,6 +137,8 @@ public class DMResponse implements Parcelable {
Message messageDelete;
@JsonField(name = "remove_conversation")
Message removeConversation;
@JsonField(name = "disable_notifications")
Message disableNotifications;
public Message getJoinConversation() {
return joinConversation;
@ -178,6 +180,10 @@ public class DMResponse implements Parcelable {
return removeConversation;
}
public Message getDisableNotifications() {
return disableNotifications;
}
@Override
public String toString() {
return "Entry{" +
@ -191,6 +197,7 @@ public class DMResponse implements Parcelable {
", conversationRead=" + conversationRead +
", messageDelete=" + messageDelete +
", removeConversation=" + removeConversation +
", disableNotifications=" + disableNotifications +
'}';
}

View File

@ -35,6 +35,7 @@ import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.activity_home_content.view.*
import kotlinx.android.synthetic.main.fragment_messages_conversation_info.*
import kotlinx.android.synthetic.main.header_message_conversation_info.view.*
import kotlinx.android.synthetic.main.layout_toolbar_message_conversation_title.*
import org.mariotaku.chameleon.Chameleon
import org.mariotaku.chameleon.ChameleonUtils
@ -50,6 +51,7 @@ import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.constant.profileImageStyleKey
import org.mariotaku.twidere.extension.model.displayAvatarTo
import org.mariotaku.twidere.extension.model.getConversationName
import org.mariotaku.twidere.extension.model.notificationDisabled
import org.mariotaku.twidere.fragment.BaseFragment
import org.mariotaku.twidere.fragment.iface.IToolBarSupportFragment
import org.mariotaku.twidere.model.ItemCounts
@ -177,14 +179,18 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
override fun getItemCount(): Int {
val conversation = this.conversation ?: return 0
itemCounts[ITEM_INDEX_HEADER] = 1
itemCounts[ITEM_INDEX_ITEM] = conversation.participants.size
return itemCounts.itemCount
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder.itemViewType) {
VIEW_TYPE_HEADER -> {
(holder as HeaderViewHolder).display(this.conversation!!)
}
VIEW_TYPE_USER -> {
val user = this.conversation!!.participants[position - itemCounts.getItemStartPosition(position)]
val user = this.conversation!!.participants[position - itemCounts.getItemStartPosition(ITEM_INDEX_ITEM)]
(holder as SimpleUserViewHolder).displayUser(user)
}
}
@ -223,8 +229,15 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
}
internal class HeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val muteSwitch = itemView.muteNotifications
fun display(conversation: ParcelableMessageConversation) {
muteSwitch.isChecked = conversation.notificationDisabled
}
companion object {
const val layoutResource = R.layout.header_message_conversation_info
}
}
}

View File

@ -229,7 +229,7 @@ class GetMessagesTask(
1.0 - (i.toDouble() / result.size))
val mc = conversations.addConversation(message.conversation_id, details, message,
setOf(dm.sender, dm.recipient))
mc.request_cursor = "page:$page"
mc?.request_cursor = "page:$page"
}
return DatabaseUpdateData(conversations.values, emptyList())
}
@ -381,7 +381,7 @@ class GetMessagesTask(
}
val messagesMap = messages.groupBy(ParcelableMessage::conversation_id)
for ((k, v) in respConversations) {
val recentMessage = messagesMap[k]?.maxBy(ParcelableMessage::message_timestamp) ?: continue
val recentMessage = messagesMap[k]?.maxBy(ParcelableMessage::message_timestamp)
val participants = respUsers.filterKeys { userId ->
v.participants.any { it.userId == userId }
}.values
@ -391,7 +391,8 @@ class GetMessagesTask(
else -> ConversationType.ONE_TO_ONE
}
val conversation = conversations.addConversation(k, account, recentMessage, participants,
conversationType)
conversationType) ?: continue
if (conversation.id in conversationDeletions) continue
conversation.conversation_name = v.name
conversation.conversation_avatar = v.avatarImageHttps
conversation.request_cursor = response.cursor
@ -428,14 +429,18 @@ class GetMessagesTask(
fun storeMessages(context: Context, data: DatabaseUpdateData, details: AccountDetails,
showNotification: Boolean = false) {
val resolver = context.contentResolver
val conversationsValues = data.conversations.map {
val conversationsValues = data.conversations.filterNot {
it.id in data.deleteConversations
}.map {
val values = ParcelableMessageConversationValuesCreator.create(it)
if (it._id > 0) {
values.put(Conversations._ID, it._id)
}
return@map values
}
val messagesValues = data.messages.map(ParcelableMessageValuesCreator::create)
val messagesValues = data.messages.filterNot {
data.deleteMessages[it.conversation_id]?.contains(it.id) ?: false
}.map(ParcelableMessageValuesCreator::create)
for ((conversationId, messageIds) in data.deleteMessages) {
val where = Expression.and(Expression.equalsArgs(Messages.ACCOUNT_KEY),
@ -525,11 +530,12 @@ class GetMessagesTask(
internal fun MutableMap<String, ParcelableMessageConversation>.addConversation(
conversationId: String,
details: AccountDetails,
message: ParcelableMessage,
message: ParcelableMessage?,
users: Collection<User>,
conversationType: String = ConversationType.ONE_TO_ONE
): ParcelableMessageConversation {
): ParcelableMessageConversation? {
val conversation = this[conversationId] ?: run {
if (message == null) return null
val obj = ParcelableMessageConversation()
obj.id = conversationId
obj.conversation_type = conversationType
@ -537,7 +543,7 @@ class GetMessagesTask(
this[conversationId] = obj
return@run obj
}
if (message.timestamp > conversation.timestamp) {
if (message != null && message.timestamp > conversation.timestamp) {
conversation.applyFrom(message, details)
}
users.forEach { user ->

View File

@ -1,107 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.view
import android.content.Context
import android.graphics.Rect
import android.support.design.widget.CoordinatorLayout
import android.support.v4.view.ViewCompat
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.widget.TextView
import kotlinx.android.synthetic.main.layout_toolbar_message_conversation_title.view.*
import org.mariotaku.twidere.R
import org.mariotaku.twidere.extension.getFrame
import org.mariotaku.twidere.extension.getFrameRelatedTo
/**
* Created by mariotaku on 2017/2/20.
*/
class ConversationInfoTitleBehavior(
context: Context,
attrs: AttributeSet? = null
) : CoordinatorLayout.Behavior<TextView>(context, attrs) {
private val marginBottom: Float
private val marginStart: Float
private val avatarRect = Rect()
private val sourceRect = Rect()
private val destRect = Rect()
private var sourceSize: Float = Float.NaN
private var destSize: Float = Float.NaN
private var viewLaidOut: Boolean = false
init {
val a = context.obtainStyledAttributes(attrs, R.styleable.ConversationInfoTitleBehavior)
marginBottom = a.getDimension(R.styleable.ConversationInfoTitleBehavior_behavior_titleMarginBottom, 0f)
marginStart = a.getDimension(R.styleable.ConversationInfoTitleBehavior_behavior_titleMarginStart, 0f)
a.recycle()
}
override fun layoutDependsOn(parent: CoordinatorLayout, child: TextView, dependency: View): Boolean {
return dependency.id == R.id.appBarConversationAvatar
}
override fun onLayoutChild(parent: CoordinatorLayout, child: TextView, layoutDirection: Int): Boolean {
val conversationAvatar = parent.getDependencies(child).first()
val appBar = conversationAvatar.parent as View
conversationAvatar.getFrame(avatarRect)
if (!viewLaidOut) {
sourceSize = child.textSize
destSize = parent.conversationName.textSize
viewLaidOut = true
}
if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
child.right = Math.round(avatarRect.left - marginStart)
child.left = child.right - child.measuredWidth
} else {
child.left = Math.round(avatarRect.right + marginStart)
child.right = child.left + child.measuredWidth
}
child.bottom = Math.round(avatarRect.centerY() - marginBottom)
child.top = child.bottom - child.measuredHeight
child.getFrameRelatedTo(sourceRect)
appBar.conversationName.getFrameRelatedTo(destRect)
return true
}
override fun onDependentViewChanged(parent: CoordinatorLayout, child: TextView, dependency: View): Boolean {
val behavior = (dependency.layoutParams as CoordinatorLayout.LayoutParams).behavior as ConversationInfoAvatarBehavior
val percent = behavior.dependentPercent
child.pivotX = child.width.toFloat()
child.pivotY = child.height.toFloat()
child.translationX = (destRect.left - sourceRect.left) * percent
child.translationY = (destRect.top - sourceRect.top) * percent
child.setTextSize(TypedValue.COMPLEX_UNIT_PX, sourceSize + (destSize - sourceSize) * percent)
if (percent >= 1) {
child.visibility = View.INVISIBLE
parent.conversationName.visibility = View.VISIBLE
} else {
child.visibility = View.VISIBLE
parent.conversationName.visibility = View.INVISIBLE
}
return true
}
}

View File

@ -24,10 +24,7 @@ import android.view.View
import kotlinx.android.synthetic.main.list_item_message_entry.view.*
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.MessagesEntriesAdapter
import org.mariotaku.twidere.extension.model.displayAvatarTo
import org.mariotaku.twidere.extension.model.getConversationName
import org.mariotaku.twidere.extension.model.getSummaryText
import org.mariotaku.twidere.extension.model.timestamp
import org.mariotaku.twidere.extension.model.*
import org.mariotaku.twidere.model.ParcelableMessageConversation
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
@ -44,6 +41,7 @@ class MessageEntryViewHolder(itemView: View, val adapter: MessagesEntriesAdapter
private val profileImage by lazy { itemView.profileImage }
private val typeIndicator by lazy { itemView.typeIndicator }
private val stateIndicator by lazy { itemView.stateIndicator }
private val readIndicator by lazy { itemView.readIndicator }
private val unreadCount by lazy { itemView.unreadCount }
init {
@ -65,16 +63,22 @@ class MessageEntryViewHolder(itemView: View, val adapter: MessagesEntriesAdapter
this.text.text = conversation.getSummaryText(itemView.context, adapter.userColorNameManager,
adapter.nameFirst)
if (conversation.is_outgoing) {
stateIndicator.visibility = View.VISIBLE
stateIndicator.setImageResource(R.drawable.ic_message_type_outgoing)
readIndicator.visibility = View.VISIBLE
readIndicator.setImageResource(R.drawable.ic_message_type_outgoing)
} else {
stateIndicator.visibility = View.GONE
readIndicator.visibility = View.GONE
}
if (conversation.conversation_type == ConversationType.ONE_TO_ONE) {
typeIndicator.visibility = View.GONE
} else {
typeIndicator.visibility = View.VISIBLE
}
if (conversation.notificationDisabled) {
stateIndicator.visibility = View.VISIBLE
stateIndicator.setImageResource(R.drawable.ic_message_type_speaker_muted)
} else {
stateIndicator.visibility = View.GONE
}
conversation.displayAvatarTo(adapter.mediaLoader, profileImage)
if (conversation.unread_count > 0) {
unreadCount.visibility = View.VISIBLE

View File

@ -21,11 +21,22 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/element_spacing_normal">
<org.mariotaku.twidere.view.FixedTextView
style="?android:listSeparatorTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="@dimen/element_spacing_normal"
android:text="@string/title_conversation"
android:textColor="?colorAccent"/>
<android.support.v7.widget.SwitchCompat
android:layout_width="match_parent"
android:id="@+id/muteNotifications"
android:layout_height="wrap_content"
android:minHeight="@dimen/element_size_normal"
android:padding="@dimen/element_spacing_normal"

View File

@ -49,7 +49,6 @@
android:contentDescription="@string/profile_image"
tools:src="@drawable/ic_profile_image_default_group"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -98,12 +97,12 @@
android:id="@+id/stateIndicator"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginLeft="@dimen/element_spacing_small"
android:layout_marginStart="@dimen/element_spacing_small"
android:layout_marginEnd="@dimen/element_spacing_small"
android:layout_marginRight="@dimen/element_spacing_small"
android:layout_weight="0"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:src="@drawable/ic_message_type_outgoing"
android:src="@drawable/ic_message_type_speaker_muted"
tools:tint="?android:textColorSecondary"/>
<org.mariotaku.twidere.view.ShortTimeView
@ -126,6 +125,18 @@
android:minHeight="24dp"
android:orientation="horizontal">
<org.mariotaku.twidere.view.IconActionView
android:id="@+id/readIndicator"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginEnd="@dimen/element_spacing_small"
android:layout_marginRight="@dimen/element_spacing_small"
android:layout_weight="0"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:src="@drawable/ic_message_type_outgoing"
tools:tint="?android:textColorSecondary"/>
<org.mariotaku.twidere.view.TimelineContentTextView
android:id="@+id/text"
android:layout_width="0dp"

View File

@ -1090,6 +1090,7 @@
<string name="title_blocked_users">Blocked users</string>
<string name="title_browser_sign_in">Browser sign in</string>
<string name="title_compose">Compose</string>
<string name="title_conversation">Conversation</string>
<string name="title_dialog_sync_connect_to">Connect to…</string>
<string name="title_direct_messages">Messages</string>
<string name="title_direct_messages_conversation_info">Conversation info</string>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>ic_message_type_speaker_muted-mdpi</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Action-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="ic_message_type_speaker_muted-mdpi">
<path d="M11,8 C11,6.82 10.32,5.80666667 9.33333333,5.31333333 L9.33333333,6.78666667 L10.9666667,8.42 C10.9866667,8.28666667 11,8.14666667 11,8 L11,8 Z M12.6666667,8 C12.6666667,8.62666667 12.5333333,9.21333333 12.3066667,9.76 L13.3133333,10.7666667 C13.7533333,9.94 14,9 14,8 C14,5.14666667 12.0066667,2.76 9.33333333,2.15333333 L9.33333333,3.52666667 C11.26,4.1 12.6666667,5.88666667 12.6666667,8 Z M2.84666667,2 L2,2.84666667 L5.15333333,6 L2,6 L2,10 L4.66666667,10 L8,13.3333333 L8,8.84666667 L10.8333333,11.68 C10.3866667,12.0266667 9.88666667,12.3 9.33333333,12.4666667 L9.33333333,13.84 C10.2533333,13.6333333 11.0866667,13.2066667 11.7933333,12.6333333 L13.1533333,14 L14,13.1533333 L8,7.15333333 L2.84666667,2 Z M8,2.66666667 L6.60666667,4.06 L8,5.45333333 L8,2.66666667 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
<polygon id="Shape" points="0 0 16 0 16 16 0 16"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB