added basic user/follow intent support

supports toggle notification for dm
This commit is contained in:
Mariotaku Lee 2017-02-25 22:05:52 +08:00
parent e0d192c2e3
commit 76820c1a3c
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
18 changed files with 414 additions and 42 deletions

View File

@ -76,6 +76,11 @@ public interface PrivateDirectMessagesResources extends PrivateResources {
@POST("/dm/new.json")
DMResponse sendDm(@Param NewDm newDm) throws MicroBlogException;
@POST("/dm/conversation/{conversation_id}/add_participants.json")
DMResponse addParticipants(@Path("conversation_id") String conversationId,
@Param(value = "participant_ids", arrayDelimiter = ',') String[] participantIds)
throws MicroBlogException;
@POST("/dm/destroy.json")
ResponseCode destroyDm(@Param("dm_id") String id) throws MicroBlogException;

View File

@ -234,10 +234,10 @@ public class ParcelableMessageConversation implements Parcelable {
String GROUP = "group";
}
@StringDef({ExtrasType.FANFOU, ExtrasType.TWITTER_OFFICIAL})
@StringDef({ExtrasType.DEFAULT, ExtrasType.TWITTER_OFFICIAL})
@Retention(RetentionPolicy.SOURCE)
public @interface ExtrasType {
String FANFOU = "fanfou";
String DEFAULT = "default";
String TWITTER_OFFICIAL = "twitter_official";
}

View File

@ -0,0 +1,72 @@
/*
* Twidere - Twitter client for Android
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.mariotaku.twidere.model.message.conversation;
import android.os.Parcel;
import android.os.Parcelable;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import org.mariotaku.microblog.library.twitter.model.DMResponse;
/**
* Created by mariotaku on 2017/2/13.
*/
@ParcelablePlease
@JsonObject
public class DefaultConversationExtras extends ConversationExtras implements Parcelable {
@JsonField(name = "notifications_disabled")
public boolean notificationsDisabled;
@Override
public String toString() {
return "DefaultConversationExtras{" +
"notificationsDisabled=" + notificationsDisabled +
"} " + super.toString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
DefaultConversationExtrasParcelablePlease.writeToParcel(this, dest, flags);
}
public static final Creator<DefaultConversationExtras> CREATOR = new Creator<DefaultConversationExtras>() {
public DefaultConversationExtras createFromParcel(Parcel source) {
DefaultConversationExtras target = new DefaultConversationExtras();
DefaultConversationExtrasParcelablePlease.readFromParcel(target, source);
return target;
}
public DefaultConversationExtras[] newArray(int size) {
return new DefaultConversationExtras[size];
}
};
}

View File

@ -300,7 +300,7 @@ public class ShapedImageView extends ImageView {
final int contentWidth = contentRight - contentLeft,
contentHeight = contentBottom - contentTop;
final int size = Math.min(contentWidth, contentHeight);
if (mShadowBitmap != null) {
if (mShadowBitmap != null && mDrawShadow) {
canvas.drawBitmap(mShadowBitmap, contentLeft + (contentWidth - size) / 2 - mShadowRadius,
contentTop + (contentHeight - size) / 2 - mShadowRadius, null);
}
@ -468,7 +468,7 @@ public class ShapedImageView extends ImageView {
}
private void updateShadowBitmap() {
if (useOutline()) return;
if (useOutline() || !mDrawShadow) return;
final int width = getWidth(), height = getHeight();
if (width <= 0 || height <= 0) return;
final int contentLeft = getPaddingLeft(), contentTop = getPaddingTop(),

View File

@ -281,6 +281,11 @@ class WebLinkHandlerActivity : Activity() {
val tweetId = uri.getQueryParameter("tweet_id") ?: return Pair(null, false)
return Pair(IntentUtils.status(null, tweetId), true)
}
"user", "follow" -> {
val userKey = uri.getQueryParameter("user_id")?.let { UserKey(it, "twitter.com") }
val screenName = uri.getQueryParameter("screen_name")
return Pair(IntentUtils.userProfile(null, userKey, screenName), true)
}
}
return Pair(null, false)
}

View File

@ -9,6 +9,7 @@ import org.mariotaku.twidere.model.ParcelableMessageConversation
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
import org.mariotaku.twidere.model.ParcelableMessageConversation.ExtrasType
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.message.conversation.DefaultConversationExtras
import org.mariotaku.twidere.model.message.conversation.TwitterOfficialConversationExtras
import org.mariotaku.twidere.util.MediaLoaderWrapper
import org.mariotaku.twidere.util.UserColorNameManager
@ -86,12 +87,34 @@ val ParcelableMessageConversation.readOnly: Boolean
return false
}
val ParcelableMessageConversation.notificationDisabled: Boolean
var ParcelableMessageConversation.notificationDisabled: Boolean
get() {
when (conversation_extras_type) {
ExtrasType.TWITTER_OFFICIAL -> {
return (conversation_extras as? TwitterOfficialConversationExtras)?.notificationsDisabled ?: false
}
else -> {
return (conversation_extras as? DefaultConversationExtras)?.notificationsDisabled ?: false
}
}
}
set(value) {
when (conversation_extras_type) {
ExtrasType.TWITTER_OFFICIAL -> {
val extras = conversation_extras as? TwitterOfficialConversationExtras ?: run {
val obj = TwitterOfficialConversationExtras()
conversation_extras = obj
return@run obj
}
extras.notificationsDisabled = value
}
else -> {
val extras = conversation_extras as? DefaultConversationExtras ?: run {
val obj = DefaultConversationExtras()
conversation_extras = obj
return@run obj
}
extras.notificationsDisabled = value
}
}
return false
}

View File

@ -19,8 +19,10 @@
package org.mariotaku.twidere.fragment.message
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.support.v4.app.FragmentActivity
@ -34,6 +36,7 @@ import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.Toolbar
import android.view.*
import android.widget.CompoundButton
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.*
@ -45,10 +48,11 @@ import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.useCursor
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.R
import org.mariotaku.twidere.activity.UserSelectorActivity
import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter
import org.mariotaku.twidere.adapter.iface.IItemCountsAdapter
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_CONVERSATION_ID
import org.mariotaku.twidere.constant.IntentConstants
import org.mariotaku.twidere.constant.IntentConstants.*
import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.constant.profileImageStyleKey
import org.mariotaku.twidere.extension.applyTheme
@ -65,7 +69,9 @@ import org.mariotaku.twidere.fragment.message.MessageConversationInfoFragment.Co
import org.mariotaku.twidere.fragment.message.MessageConversationInfoFragment.ConversationInfoAdapter.Companion.VIEW_TYPE_SPACE
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
import org.mariotaku.twidere.task.twitter.message.AddParticipantsTask
import org.mariotaku.twidere.task.twitter.message.DestroyConversationTask
import org.mariotaku.twidere.task.twitter.message.SetConversationNotificationDisabledTask
import org.mariotaku.twidere.util.IntentUtils
import org.mariotaku.twidere.view.holder.SimpleUserViewHolder
import java.lang.ref.WeakReference
@ -105,6 +111,18 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
startActivity(IntentUtils.userProfile(user))
}
override fun onAddUserClick(position: Int) {
val conversation = adapter.conversation ?: return
val intent = Intent(IntentConstants.INTENT_ACTION_SELECT_USER)
intent.putExtra(EXTRA_ACCOUNT_KEY, conversation.account_key)
intent.setClass(context, UserSelectorActivity::class.java)
startActivityForResult(intent, REQUEST_CONVERSATION_ADD_USER)
}
override fun onDisableNotificationChanged(disabled: Boolean) {
performSetNotificationDisabled(disabled)
}
}
recyclerView.adapter = adapter
recyclerView.layoutManager = LayoutManager(context)
@ -123,9 +141,25 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
conversationTitle.setTextColor(ChameleonUtils.getColorDependent(theme.colorToolbar))
conversationSubtitle.setTextColor(ChameleonUtils.getColorDependent(theme.colorToolbar))
editButton.setOnClickListener {
executeAfterFragmentResumed { fragment ->
val df = EditInfoDialogFragment()
df.show(fragment.childFragmentManager, "edit_info")
}
}
loaderManager.initLoader(0, null, this)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_CONVERSATION_ADD_USER -> {
if (resultCode == Activity.RESULT_OK && data != null) {
val user = data.getParcelableExtra<ParcelableUser>(EXTRA_USER)
performAddParticipant(user)
}
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@ -185,9 +219,7 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
val task = DestroyConversationTask(context, accountKey, conversationId)
task.callback = callback@ { succeed ->
val f = weakThis.get() ?: return@callback
f.executeAfterFragmentResumed { fragment ->
val df = fragment.childFragmentManager.findFragmentByTag("leave_conversation_progress") as? DialogFragment
df?.dismiss()
f.dismissAlertDialogThen("leave_conversation_progress") {
if (succeed) {
activity?.setResult(RESULT_CLOSE)
activity?.finish()
@ -197,6 +229,37 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
TaskStarter.execute(task)
}
private fun performAddParticipant(user: ParcelableUser) {
ProgressDialogFragment.show(childFragmentManager, "add_participant_progress")
val weakThis = WeakReference(this)
val task = AddParticipantsTask(context, accountKey, conversationId, arrayOf(user.key.id))
task.callback = callback@ { succeed ->
val f = weakThis.get() ?: return@callback
f.dismissAlertDialogThen("add_participant_progress") {}
}
TaskStarter.execute(task)
}
private fun performSetNotificationDisabled(disabled: Boolean) {
ProgressDialogFragment.show(childFragmentManager, "set_notifications_disabled_progress")
val weakThis = WeakReference(this)
val task = SetConversationNotificationDisabledTask(context, accountKey, conversationId, disabled)
task.callback = callback@ { succeed ->
val f = weakThis.get() ?: return@callback
f.dismissAlertDialogThen("set_notifications_disabled_progress") {}
}
TaskStarter.execute(task)
}
private inline fun dismissAlertDialogThen(tag: String, crossinline action: BaseFragment.() -> Unit) {
executeAfterFragmentResumed { fragment ->
val df = fragment.childFragmentManager.findFragmentByTag(tag) as? DialogFragment
df?.dismiss()
action(fragment)
}
}
class ConversationInfoLoader(
context: Context,
val accountKey: UserKey,
@ -262,7 +325,7 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
when (viewType) {
VIEW_TYPE_HEADER -> {
val view = inflater.inflate(HeaderViewHolder.layoutResource, parent, false)
return HeaderViewHolder(view)
return HeaderViewHolder(view, this)
}
VIEW_TYPE_USER -> {
val view = inflater.inflate(R.layout.list_item_conversation_info_user, parent, false)
@ -310,6 +373,7 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
interface Listener {
fun onUserClick(position: Int) {}
fun onAddUserClick(position: Int) {}
fun onDisableNotificationChanged(disabled: Boolean) {}
}
companion object {
@ -359,16 +423,21 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
}
}
internal class HeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
internal class HeaderViewHolder(itemView: View, adapter: ConversationInfoAdapter) : RecyclerView.ViewHolder(itemView) {
private val muteSwitch = itemView.muteNotifications
private val listener = CompoundButton.OnCheckedChangeListener { button, checked ->
adapter.listener?.onDisableNotificationChanged(checked)
}
fun display(conversation: ParcelableMessageConversation) {
muteSwitch.setOnCheckedChangeListener(null)
muteSwitch.isChecked = conversation.notificationDisabled
muteSwitch.setOnCheckedChangeListener(listener)
}
companion object {
const val layoutResource = R.layout.header_message_conversation_info
}
}
@ -385,6 +454,25 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
}
class EditInfoDialogFragment : BaseDialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val actions = arrayOf(Action(getString(R.string.action_edit_conversation_name), "name"),
Action(getString(R.string.action_edit_conversation_avatar), "avatar"))
val builder = AlertDialog.Builder(context)
builder.setItems(actions.map(Action::title).toTypedArray()) { dialog, which ->
}
val dialog = builder.create()
dialog.setOnShowListener {
it as AlertDialog
it.applyTheme()
}
return dialog
}
data class Action(val title: String, val type: String)
}
class DestroyConversationConfirmDialogFragment : BaseDialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(context)
@ -405,5 +493,6 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
companion object {
const val RESULT_CLOSE = 101
const val REQUEST_CONVERSATION_ADD_USER = 101
}
}

View File

@ -51,7 +51,7 @@ class ExtensionsListLoader(
extensions.add(ExtensionInfo(info, packageManager))
}
}
extensions.sort(ExtensionInfoComparator(Collator.getInstance()))
Collections.sort(extensions, ExtensionInfoComparator(Collator.getInstance()))
return extensions
}

View File

@ -0,0 +1,71 @@
/*
* 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.task.twitter.message
import android.accounts.AccountManager
import android.content.Context
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.extension.model.isOfficial
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.task.ExceptionHandlingAbstractTask
/**
* Created by mariotaku on 2017/2/25.
*/
class AddParticipantsTask(
context: Context,
val accountKey: UserKey,
val conversationId: String,
val participantIds: Array<String>
) : ExceptionHandlingAbstractTask<Unit?, Boolean, MicroBlogException, ((Boolean) -> Unit)?>(context) {
override fun onExecute(params: Unit?): Boolean {
val account = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true) ?:
throw MicroBlogException("No account")
val microBlog = account.newMicroBlogInstance(context, cls = MicroBlog::class.java)
val addData = requestAddParticipants(microBlog, account)
GetMessagesTask.storeMessages(context, addData, account)
return true
}
override fun afterExecute(callback: ((Boolean) -> Unit)?, result: Boolean?, exception: MicroBlogException?) {
callback?.invoke(result ?: false)
}
private fun requestAddParticipants(microBlog: MicroBlog, account: AccountDetails):
GetMessagesTask.DatabaseUpdateData {
when (account.type) {
AccountType.TWITTER -> {
if (account.isOfficial(context)) {
val response = microBlog.addParticipants(conversationId, participantIds);
return GetMessagesTask.createDatabaseUpdateData(context, account, response)
}
}
}
throw MicroBlogException("Adding participants is not supported")
}
}

View File

@ -40,6 +40,7 @@ import org.mariotaku.twidere.extension.model.timestamp
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
import org.mariotaku.twidere.model.event.GetMessagesTaskEvent
import org.mariotaku.twidere.model.message.conversation.DefaultConversationExtras
import org.mariotaku.twidere.model.message.conversation.TwitterOfficialConversationExtras
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.AccountUtils.getAccountDetails
@ -165,13 +166,23 @@ class GetMessagesTask(
val message = ParcelableMessageUtils.fromMessage(accountKey, dm, false,
1.0 - (i.toDouble() / received.size))
insertMessages.add(message)
conversations.addConversation(message.conversation_id, details, message, setOf(dm.sender, dm.recipient))
val conversation = conversations.addConversation(message.conversation_id, details,
message, setOf(dm.sender, dm.recipient)) ?: return@forEachIndexed
conversation.conversation_extras_type = ParcelableMessageConversation.ExtrasType.DEFAULT
if (conversation.conversation_extras == null) {
conversation.conversation_extras = DefaultConversationExtras()
}
}
sent.forEachIndexed { i, dm ->
val message = ParcelableMessageUtils.fromMessage(accountKey, dm, true,
1.0 - (i.toDouble() / sent.size))
insertMessages.add(message)
conversations.addConversation(message.conversation_id, details, message, setOf(dm.sender, dm.recipient))
val conversation = conversations.addConversation(message.conversation_id, details,
message, setOf(dm.sender, dm.recipient)) ?: return@forEachIndexed
conversation.conversation_extras_type = ParcelableMessageConversation.ExtrasType.DEFAULT
if (conversation.conversation_extras == null) {
conversation.conversation_extras = DefaultConversationExtras()
}
}
return DatabaseUpdateData(conversations.values, insertMessages)
}

View File

@ -53,7 +53,7 @@ class MarkMessageReadTask(
val account = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true) ?:
throw MicroBlogException("No account")
val microBlog = account.newMicroBlogInstance(context, cls = MicroBlog::class.java)
val conversation = findConversation(accountKey, conversationId)
val conversation = findConversation(context, accountKey, conversationId)
val lastReadEvent = conversation?.let {
return@let performMarkRead(microBlog, account, conversation)
} ?: return false
@ -92,22 +92,6 @@ class MarkMessageReadTask(
return Pair(message.id, message.timestamp)
}
private fun findConversation(accountKey: UserKey, conversationId: String): ParcelableMessageConversation? {
val deleteWhere = Expression.and(Expression.equalsArgs(Conversations.ACCOUNT_KEY),
Expression.equalsArgs(Conversations.CONVERSATION_ID)).sql
val deleteWhereArgs = arrayOf(accountKey.toString(), conversationId)
@SuppressLint("Recycle")
val cur = context.contentResolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS,
deleteWhere, deleteWhereArgs, null) ?: return null
try {
if (cur.moveToFirst()) {
return ParcelableMessageConversationCursorIndices.fromCursor(cur)
}
} finally {
cur.close()
}
return null
}
private fun findRecentMessage(accountKey: UserKey, conversationId: String): ParcelableMessage? {
val where = Expression.and(Expression.equalsArgs(Messages.ACCOUNT_KEY),
@ -133,5 +117,24 @@ class MarkMessageReadTask(
return Pair(id, maxEntryTimestamp)
}
companion object {
fun findConversation(context: Context, accountKey: UserKey, conversationId: String):
ParcelableMessageConversation? {
val deleteWhere = Expression.and(Expression.equalsArgs(Conversations.ACCOUNT_KEY),
Expression.equalsArgs(Conversations.CONVERSATION_ID)).sql
val deleteWhereArgs = arrayOf(accountKey.toString(), conversationId)
@SuppressLint("Recycle")
val cur = context.contentResolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS,
deleteWhere, deleteWhereArgs, null) ?: return null
try {
if (cur.moveToFirst()) {
return ParcelableMessageConversationCursorIndices.fromCursor(cur)
}
} finally {
cur.close()
}
return null
}
}
}

View File

@ -73,7 +73,8 @@ class SendMessageTask(
result.conversationIds.singleOrNull(), true))
}
private fun requestSendMessage(microBlog: MicroBlog, account: AccountDetails, message: ParcelableNewMessage): GetMessagesTask.DatabaseUpdateData {
private fun requestSendMessage(microBlog: MicroBlog, account: AccountDetails,
message: ParcelableNewMessage): GetMessagesTask.DatabaseUpdateData {
when (account.type) {
AccountType.TWITTER -> {
if (account.isOfficial(context)) {

View File

@ -0,0 +1,86 @@
/*
* 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.task.twitter.message
import android.accounts.AccountManager
import android.content.Context
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.extension.model.isOfficial
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.extension.model.notificationDisabled
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.task.ExceptionHandlingAbstractTask
/**
* Created by mariotaku on 2017/2/25.
*/
class SetConversationNotificationDisabledTask(
context: Context,
val accountKey: UserKey,
val conversationId: String,
val notificationDisabled: Boolean
) : ExceptionHandlingAbstractTask<Unit?, Boolean, MicroBlogException, ((Boolean) -> Unit)?>(context) {
override fun onExecute(params: Unit?): Boolean {
val account = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true) ?:
throw MicroBlogException("No account")
val microBlog = account.newMicroBlogInstance(context, cls = MicroBlog::class.java)
val addData = requestSetNotificationDisabled(microBlog, account)
GetMessagesTask.storeMessages(context, addData, account)
return true
}
override fun afterExecute(callback: ((Boolean) -> Unit)?, result: Boolean?, exception: MicroBlogException?) {
callback?.invoke(result ?: false)
}
private fun requestSetNotificationDisabled(microBlog: MicroBlog, account: AccountDetails):
GetMessagesTask.DatabaseUpdateData {
when (account.type) {
AccountType.TWITTER -> {
if (account.isOfficial(context)) {
val response = if (notificationDisabled) {
microBlog.enableDmConversations(conversationId);
} else {
microBlog.disableDmConversations(conversationId);
}
val conversation = MarkMessageReadTask.findConversation(context, accountKey,
conversationId) ?: return GetMessagesTask.DatabaseUpdateData(emptyList(), emptyList())
if (response.isSuccessful) {
conversation.notificationDisabled = notificationDisabled
}
return GetMessagesTask.DatabaseUpdateData(listOf(conversation), emptyList())
}
}
}
val conversation = MarkMessageReadTask.findConversation(context, accountKey,
conversationId) ?: return GetMessagesTask.DatabaseUpdateData(emptyList(), emptyList())
conversation.notificationDisabled = notificationDisabled
// Don't finish too fast
Thread.sleep(300L)
return GetMessagesTask.DatabaseUpdateData(listOf(conversation), emptyList())
}
}

View File

@ -76,7 +76,7 @@ object IntentUtils {
}
fun userProfile(accountKey: UserKey?, userKey: UserKey?, screenName: String?,
@Referral referral: String? = null, profileUrl: String?): Intent {
@Referral referral: String? = null, profileUrl: String? = null): Intent {
val uri = LinkCreator.getTwidereUserLink(accountKey, userKey, screenName)
val intent = Intent(Intent.ACTION_VIEW, uri)
if (referral != null) {

View File

@ -60,7 +60,6 @@ class AppBarChildBehavior(
private val dependencyRect = Rect()
private val thisRect = Rect()
private val thisInitRect = Rect()
private val targetRect = Rect()
private val tempRect = Rect()
@ -95,7 +94,7 @@ class AppBarChildBehavior(
val dependency = parent.getDependencies(child).first()
dependency.getFrameRelatedTo(dependencyRect, parent)
child.layoutRelatedTo(dependencyRect, layoutDirection)
child.layoutRelatedTo(parent, dependencyRect, layoutDirection)
child.getFrameRelatedTo(thisRect, parent)
target.getFrameRelatedTo(targetRect, parent)
@ -116,7 +115,7 @@ class AppBarChildBehavior(
return true
}
internal fun View.layoutRelatedTo(frame: Rect, layoutDirection: Int) {
internal fun View.layoutRelatedTo(parent: CoordinatorLayout, frame: Rect, layoutDirection: Int) {
val verticalRule = alignmentRule and VERTICAL_MASK
val horizontalRule = alignmentRule and HORIZONTAL_MASK
tempRect.set(0, 0, measuredWidth, measuredHeight)

View File

@ -82,7 +82,7 @@
android:layout_height="wrap_content"
android:elevation="8dp"
android:ellipsize="end"
android:minLines="1"
android:maxLines="1"
android:textAppearance="?android:textAppearanceLarge"
android:textColor="?android:textColorPrimary"
android:textStyle="normal"
@ -102,7 +102,7 @@
android:layout_height="wrap_content"
android:elevation="8dp"
android:ellipsize="end"
android:minLines="1"
android:maxLines="1"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"
android:textStyle="normal"

View File

@ -36,6 +36,7 @@
android:layout_height="match_parent"
android:layout_margin="@dimen/element_spacing_normal"
android:layout_weight="0"
app:sivDrawShadow="false"
app:sivShape="circle"
tools:src="@drawable/ic_profile_image_default_group"/>
@ -52,6 +53,8 @@
android:id="@+id/conversationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"
tools:text="Conversation name"/>
@ -60,6 +63,8 @@
android:id="@+id/conversationSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"
tools:text="Conversation summary"/>

View File

@ -1224,4 +1224,6 @@
<string name="vibration">Vibration</string>
<string name="message_destroy_conversation_confirm">Leave this conversation?</string>
<string name="action_edit_conversation_name">Edit name</string>
<string name="action_edit_conversation_avatar">Edit icon</string>
</resources>