added basic user/follow intent support
supports toggle notification for dm
This commit is contained in:
parent
e0d192c2e3
commit
76820c1a3c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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(),
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class ExtensionsListLoader(
|
|||
extensions.add(ExtensionInfo(info, packageManager))
|
||||
}
|
||||
}
|
||||
extensions.sort(ExtensionInfoComparator(Collator.getInstance()))
|
||||
Collections.sort(extensions, ExtensionInfoComparator(Collator.getInstance()))
|
||||
return extensions
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue