From fbaf4dd0da70e6f7321115431b86c9939e49768a Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 12 Apr 2017 19:25:10 +0800 Subject: [PATCH] implemented twitter retweet/favorite intent handling --- twidere/src/.google.commit-id | 2 +- .../activity/WebLinkHandlerActivity.kt | 21 +- .../content/AbsStatusDialogActivity.kt | 76 ++++++ .../content/FavoriteConfirmDialogActivity.kt | 22 +- .../content/RetweetQuoteDialogActivity.kt | 26 +- .../content/AbsStatusDialogFragment.kt | 145 ++++++++++ .../content/FavoriteConfirmDialogFragment.kt | 113 +++----- .../content/RetweetQuoteDialogFragment.kt | 248 +++++++++--------- .../org/mariotaku/twidere/util/IntentUtils.kt | 5 +- .../layout/dialog_status_favorite_confirm.xml | 2 +- .../layout/dialog_status_quote_retweet.xml | 2 +- 11 files changed, 415 insertions(+), 247 deletions(-) create mode 100644 twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/AbsStatusDialogActivity.kt create mode 100644 twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/AbsStatusDialogFragment.kt diff --git a/twidere/src/.google.commit-id b/twidere/src/.google.commit-id index 3899e14ee..0d2d55aab 100644 --- a/twidere/src/.google.commit-id +++ b/twidere/src/.google.commit-id @@ -1 +1 @@ -e996a88227d4a77ebe6739b7286d744f2023e398 +ea793d047ce90d44b4d0d8b67cb69c0b99ca173e diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/WebLinkHandlerActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/WebLinkHandlerActivity.kt index f8ea7c588..587655100 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/WebLinkHandlerActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/WebLinkHandlerActivity.kt @@ -8,6 +8,8 @@ import android.text.TextUtils import org.mariotaku.ktextension.toLongOr import org.mariotaku.twidere.R import org.mariotaku.twidere.TwidereConstants.* +import org.mariotaku.twidere.activity.content.FavoriteConfirmDialogActivity +import org.mariotaku.twidere.activity.content.RetweetQuoteDialogActivity import org.mariotaku.twidere.app.TwidereApplication import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.util.Analyzer @@ -276,14 +278,27 @@ class WebLinkHandlerActivity : Activity() { handledIntent.putExtra(Intent.EXTRA_TEXT, sb.toString()) return Pair(handledIntent, true) } - "favorite", "retweet" -> { + "retweet" -> { val tweetId = uri.getQueryParameter("tweet_id") ?: return Pair(null, false) - return Pair(IntentUtils.status(null, tweetId), true) + val accountHost = USER_TYPE_TWITTER_COM + val intent = Intent(this, RetweetQuoteDialogActivity::class.java) + intent.putExtra(EXTRA_STATUS_ID, tweetId) + intent.putExtra(EXTRA_ACCOUNT_HOST, accountHost) + return Pair(intent, true) + } + "favorite", "like" -> { + val tweetId = uri.getQueryParameter("tweet_id") ?: return Pair(null, false) + val accountHost = USER_TYPE_TWITTER_COM + val intent = Intent(this, FavoriteConfirmDialogActivity::class.java) + intent.putExtra(EXTRA_STATUS_ID, tweetId) + intent.putExtra(EXTRA_ACCOUNT_HOST, accountHost) + return Pair(intent, 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(IntentUtils.userProfile(null, userKey, screenName, + accountHost = USER_TYPE_TWITTER_COM), true) } } return Pair(null, false) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/AbsStatusDialogActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/AbsStatusDialogActivity.kt new file mode 100644 index 000000000..9eb6b6b5a --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/AbsStatusDialogActivity.kt @@ -0,0 +1,76 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * 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 . + */ + +package org.mariotaku.twidere.activity.content + +import android.content.Intent +import android.os.Bundle +import org.mariotaku.twidere.TwidereConstants.REQUEST_SELECT_ACCOUNT +import org.mariotaku.twidere.activity.AccountSelectorActivity +import org.mariotaku.twidere.activity.BaseActivity +import org.mariotaku.twidere.constant.IntentConstants.* +import org.mariotaku.twidere.model.ParcelableStatus +import org.mariotaku.twidere.model.UserKey + +abstract class AbsStatusDialogActivity : BaseActivity() { + + private val statusId: String + get() = intent.getStringExtra(EXTRA_STATUS_ID) + + private val accountKey: UserKey? + get() = intent.getParcelableExtra(EXTRA_ACCOUNT_KEY) + + private val accountHost: String? + get() = intent.getStringExtra(EXTRA_ACCOUNT_HOST) + + private val status: ParcelableStatus? + get() = intent.getParcelableExtra(EXTRA_STATUS) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (savedInstanceState == null) { + val accountKey = this.accountKey + if (accountKey != null) { + showDialogFragment(accountKey, statusId, status) + } else { + val intent = Intent(this, AccountSelectorActivity::class.java) + intent.putExtra(EXTRA_SINGLE_SELECTION, true) + intent.putExtra(EXTRA_SELECT_ONLY_ITEM_AUTOMATICALLY, true) + intent.putExtra(EXTRA_ACCOUNT_HOST, accountHost) + startActivityForResult(intent, REQUEST_SELECT_ACCOUNT) + } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + REQUEST_SELECT_ACCOUNT -> { + if (resultCode == RESULT_OK && data != null) { + val accountKey = data.getParcelableExtra(EXTRA_ACCOUNT_KEY) + showDialogFragment(accountKey, statusId, status) + return + } + } + } + finish() + } + + protected abstract fun showDialogFragment(accountKey: UserKey, statusId: String, + status: ParcelableStatus?) +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/FavoriteConfirmDialogActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/FavoriteConfirmDialogActivity.kt index 8df97de34..cdef65c31 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/FavoriteConfirmDialogActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/FavoriteConfirmDialogActivity.kt @@ -19,9 +19,6 @@ package org.mariotaku.twidere.activity.content -import android.os.Bundle -import org.mariotaku.twidere.activity.BaseActivity -import org.mariotaku.twidere.constant.IntentConstants.* import org.mariotaku.twidere.fragment.content.FavoriteConfirmDialogFragment import org.mariotaku.twidere.model.ParcelableStatus import org.mariotaku.twidere.model.UserKey @@ -31,21 +28,12 @@ import org.mariotaku.twidere.model.UserKey * * Created by mariotaku on 2017/4/12. */ -class FavoriteConfirmDialogActivity : BaseActivity() { +class FavoriteConfirmDialogActivity : AbsStatusDialogActivity() { - private val status: ParcelableStatus - get() = intent.getParcelableExtra(EXTRA_STATUS) - - private val statusId: String - get() = intent.getStringExtra(EXTRA_STATUS_ID) - - private val accountKey: UserKey? - get() = intent.getParcelableExtra(EXTRA_ACCOUNT_KEY) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState == null) { - FavoriteConfirmDialogFragment.show(supportFragmentManager, accountKey, statusId, status) + override fun showDialogFragment(accountKey: UserKey, statusId: String, status: ParcelableStatus?) { + executeAfterFragmentResumed { + FavoriteConfirmDialogFragment.show(it.supportFragmentManager, accountKey, statusId, status) } } + } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/RetweetQuoteDialogActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/RetweetQuoteDialogActivity.kt index 340d2c887..7c1c872a2 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/RetweetQuoteDialogActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/content/RetweetQuoteDialogActivity.kt @@ -19,9 +19,7 @@ package org.mariotaku.twidere.activity.content -import android.os.Bundle -import org.mariotaku.twidere.activity.BaseActivity -import org.mariotaku.twidere.constant.IntentConstants.* +import org.mariotaku.twidere.constant.IntentConstants.EXTRA_TEXT import org.mariotaku.twidere.fragment.content.RetweetQuoteDialogFragment import org.mariotaku.twidere.model.ParcelableStatus import org.mariotaku.twidere.model.UserKey @@ -31,25 +29,17 @@ import org.mariotaku.twidere.model.UserKey * * Created by mariotaku on 2017/4/8. */ -class RetweetQuoteDialogActivity : BaseActivity() { - - private val status: ParcelableStatus - get() = intent.getParcelableExtra(EXTRA_STATUS) - - private val statusId: String - get() = intent.getStringExtra(EXTRA_STATUS_ID) - - private val accountKey: UserKey? - get() = intent.getParcelableExtra(EXTRA_ACCOUNT_KEY) +class RetweetQuoteDialogActivity : AbsStatusDialogActivity() { private val text: String? get() = intent.getStringExtra(EXTRA_TEXT) - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState == null) { - RetweetQuoteDialogFragment.show(supportFragmentManager, accountKey, statusId, status, - text) + override fun showDialogFragment(accountKey: UserKey, statusId: String, status: ParcelableStatus?) { + val text = this.text + executeAfterFragmentResumed { + RetweetQuoteDialogFragment.show(it.supportFragmentManager, accountKey, statusId, + status, text) } } + } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/AbsStatusDialogFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/AbsStatusDialogFragment.kt new file mode 100644 index 000000000..0e9b80eb9 --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/AbsStatusDialogFragment.kt @@ -0,0 +1,145 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * 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 . + */ + +package org.mariotaku.twidere.fragment.content + +import android.accounts.AccountManager +import android.app.Dialog +import android.content.Context +import android.content.DialogInterface +import android.os.Bundle +import android.support.v7.app.AlertDialog +import android.view.View +import android.widget.Toast +import com.bumptech.glide.Glide +import kotlinx.android.synthetic.main.list_item_status.view.* +import nl.komponents.kovenant.Promise +import nl.komponents.kovenant.combine.and +import nl.komponents.kovenant.task +import nl.komponents.kovenant.ui.failUi +import nl.komponents.kovenant.ui.promiseOnUi +import nl.komponents.kovenant.ui.successUi +import org.mariotaku.microblog.library.MicroBlog +import org.mariotaku.twidere.R +import org.mariotaku.twidere.adapter.DummyItemAdapter +import org.mariotaku.twidere.constant.IntentConstants.* +import org.mariotaku.twidere.extension.applyTheme +import org.mariotaku.twidere.extension.model.newMicroBlogInstance +import org.mariotaku.twidere.fragment.BaseDialogFragment +import org.mariotaku.twidere.model.AccountDetails +import org.mariotaku.twidere.model.ParcelableStatus +import org.mariotaku.twidere.model.UserKey +import org.mariotaku.twidere.model.util.AccountUtils +import org.mariotaku.twidere.model.util.ParcelableStatusUtils +import org.mariotaku.twidere.view.holder.StatusViewHolder +import java.lang.ref.WeakReference + +abstract class AbsStatusDialogFragment : BaseDialogFragment() { + + protected abstract val Dialog.loadProgress: View + protected abstract val Dialog.itemContent: View + + protected val status: ParcelableStatus? + get() = arguments.getParcelable(EXTRA_STATUS) + + protected val statusId: String + get() = arguments.getString(EXTRA_STATUS_ID) + + protected val accountKey: UserKey + get() = arguments.getParcelable(EXTRA_ACCOUNT_KEY) + + override final fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val builder = AlertDialog.Builder(context) + val accountKey = this.accountKey + + builder.setupAlertDialog() + + val dialog = builder.create() + dialog.setOnShowListener { dialog -> + dialog as AlertDialog + dialog.applyTheme() + + val am = AccountManager.get(context) + val details = AccountUtils.getAccountDetails(am, accountKey, true) ?: run { + dismiss() + return@setOnShowListener + } + val weakThis = WeakReference(this) + promiseOnUi { + val currentDialog = weakThis.get()?.dialog as? AlertDialog ?: return@promiseOnUi + currentDialog.loadProgress.visibility = View.VISIBLE + currentDialog.itemContent.visibility = View.GONE + currentDialog.getButton(DialogInterface.BUTTON_POSITIVE)?.isEnabled = false + currentDialog.getButton(DialogInterface.BUTTON_NEUTRAL)?.isEnabled = false + } and showStatus(context, details, statusId, status).successUi { status -> + val fragment = weakThis.get() ?: return@successUi + val currentDialog = fragment.dialog as? AlertDialog ?: return@successUi + currentDialog.getButton(DialogInterface.BUTTON_POSITIVE)?.isEnabled = true + currentDialog.getButton(DialogInterface.BUTTON_NEUTRAL)?.isEnabled = true + currentDialog.itemContent.visibility = View.VISIBLE + currentDialog.loadProgress.visibility = View.GONE + currentDialog.itemContent.isFocusable = false + currentDialog.itemContent.itemMenu.visibility = View.GONE + currentDialog.itemContent.actionButtons.visibility = View.GONE + val adapter = DummyItemAdapter(fragment.context, requestManager = Glide.with(fragment)) + adapter.setShouldShowAccountsColor(true) + val holder = StatusViewHolder(adapter, currentDialog.itemContent) + holder.displayStatus(status = status, displayInReplyTo = false) + currentDialog.onStatusLoaded(details, status, savedInstanceState) + }.failUi { + val fragment = weakThis.get()?.takeIf { it.dialog != null } ?: return@failUi + Toast.makeText(fragment.context, R.string.message_toast_error_occurred, Toast.LENGTH_SHORT).show() + fragment.dismiss() + } + } + return dialog + } + + protected abstract fun AlertDialog.Builder.setupAlertDialog() + + protected abstract fun AlertDialog.onStatusLoaded(details: AccountDetails, status: ParcelableStatus, + savedInstanceState: Bundle?) + + companion object { + + fun showStatus(context: Context, details: AccountDetails, statusId: String, + status: ParcelableStatus?): Promise { + if (status != null) { + status.apply { + if (account_key != details.key) { + my_retweet_id = null + is_favorite = false + } + account_key = details.key + account_color = details.color + } + return Promise.ofSuccess(status) + } + val microBlog = details.newMicroBlogInstance(context, MicroBlog::class.java) + val profileImageSize = context.getString(R.string.profile_image_size) + return task { + val status = ParcelableStatusUtils.fromStatus(microBlog.showStatus(statusId), + details.key, details.type, profileImageSize = profileImageSize) + status.account_color = details.color + return@task status + } + } + + } +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/FavoriteConfirmDialogFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/FavoriteConfirmDialogFragment.kt index 03f8b0bbe..35e44cab3 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/FavoriteConfirmDialogFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/FavoriteConfirmDialogFragment.kt @@ -19,111 +19,66 @@ package org.mariotaku.twidere.fragment.content -import android.accounts.AccountManager import android.app.Dialog import android.content.DialogInterface import android.os.Bundle import android.support.v4.app.FragmentManager import android.support.v7.app.AlertDialog import android.view.View -import android.widget.ImageButton -import android.widget.LinearLayout -import com.bumptech.glide.Glide import org.mariotaku.kpreferences.get import org.mariotaku.ktextension.Bundle import org.mariotaku.ktextension.set import org.mariotaku.twidere.R -import org.mariotaku.twidere.activity.content.RetweetQuoteDialogActivity -import org.mariotaku.twidere.adapter.DummyItemAdapter +import org.mariotaku.twidere.activity.content.FavoriteConfirmDialogActivity import org.mariotaku.twidere.constant.IntentConstants.* import org.mariotaku.twidere.constant.iWantMyStarsBackKey -import org.mariotaku.twidere.extension.applyTheme -import org.mariotaku.twidere.fragment.BaseDialogFragment +import org.mariotaku.twidere.model.AccountDetails import org.mariotaku.twidere.model.ParcelableStatus import org.mariotaku.twidere.model.UserKey -import org.mariotaku.twidere.model.util.AccountUtils -import org.mariotaku.twidere.view.ColorLabelRelativeLayout -import org.mariotaku.twidere.view.holder.StatusViewHolder /** * Asks user to favorite a status. * * Created by mariotaku on 2017/4/12. */ -class FavoriteConfirmDialogFragment : BaseDialogFragment() { +class FavoriteConfirmDialogFragment : AbsStatusDialogFragment() { - private val Dialog.loadProgress get() = findViewById(R.id.loadProgress) - private val Dialog.itemContent get() = findViewById(R.id.itemContent) as ColorLabelRelativeLayout - private val Dialog.itemMenu get() = findViewById(R.id.itemMenu) as ImageButton - private val Dialog.actionButtons get() = findViewById(R.id.actionButtons) as LinearLayout + override val Dialog.loadProgress: View get() = findViewById(R.id.loadProgress) - private val status: ParcelableStatus - get() = arguments.getParcelable(EXTRA_STATUS) + override val Dialog.itemContent: View get() = findViewById(R.id.itemContent) - private val accountKey: UserKey - get() = arguments.getParcelable(EXTRA_ACCOUNT_KEY) ?: status.account_key + override fun AlertDialog.Builder.setupAlertDialog() { + setTitle(R.string.title_favorite_confirm) + setView(R.layout.dialog_status_favorite_confirm) + setPositiveButton(R.string.action_favorite, null) + setNegativeButton(android.R.string.cancel, null) + } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val builder = AlertDialog.Builder(context) - val accountKey = this.accountKey - val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true)!! - val status = this.status.apply { - if (account_key != accountKey) { - is_favorite = false - } - account_key = details.key - account_color = details.color - } - - - builder.setView(R.layout.dialog_status_favorite_confirm) - builder.setTitle(R.string.title_favorite_confirm) + override fun AlertDialog.onStatusLoaded(details: AccountDetails, status: ParcelableStatus, + savedInstanceState: Bundle?) { + val positiveButton = getButton(DialogInterface.BUTTON_POSITIVE) if (preferences[iWantMyStarsBackKey]) { - builder.setPositiveButton(R.string.action_favorite, null) - } else { - builder.setPositiveButton(R.string.action_like, null) - } - builder.setNegativeButton(android.R.string.cancel, null) - val dialog = builder.create() - dialog.setOnShowListener { dialog -> - dialog as AlertDialog - dialog.applyTheme() - - val adapter = DummyItemAdapter(context, requestManager = Glide.with(this)) - adapter.setShouldShowAccountsColor(true) - val holder = StatusViewHolder(adapter, dialog.itemContent) - holder.displayStatus(status = status, displayInReplyTo = false) - - dialog.loadProgress.visibility = View.GONE - dialog.itemMenu.visibility = View.GONE - dialog.actionButtons.visibility = View.GONE - dialog.itemContent.isFocusable = false - - val positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE) - if (preferences[iWantMyStarsBackKey]) { - if (status.is_favorite) { - positiveButton.setText(R.string.action_unfavorite) - } else { - positiveButton.setText(R.string.action_favorite) - } + if (status.is_favorite) { + positiveButton.setText(R.string.action_unfavorite) } else { - if (status.is_favorite) { - positiveButton.setText(R.string.action_undo_like) - } else { - positiveButton.setText(R.string.action_like) - } + positiveButton.setText(R.string.action_favorite) } - positiveButton.setOnClickListener { - if (status.is_favorite) { - twitterWrapper.destroyFavoriteAsync(accountKey, status.id) - } else { - twitterWrapper.createFavoriteAsync(accountKey, status) - } - dismiss() + } else { + if (status.is_favorite) { + positiveButton.setText(R.string.action_undo_like) + } else { + positiveButton.setText(R.string.action_like) } - } - return dialog + positiveButton.setOnClickListener { + if (status.is_favorite) { + twitterWrapper.destroyFavoriteAsync(accountKey, status.id) + } else { + twitterWrapper.createFavoriteAsync(accountKey, status) + } + dismiss() + } + } override fun onCancel(dialog: DialogInterface) { @@ -137,7 +92,7 @@ class FavoriteConfirmDialogFragment : BaseDialogFragment() { private fun finishFavoriteConfirmActivity() { val activity = this.activity - if (activity is RetweetQuoteDialogActivity && !activity.isFinishing) { + if (activity is FavoriteConfirmDialogActivity && !activity.isFinishing) { activity.finish() } } @@ -146,8 +101,8 @@ class FavoriteConfirmDialogFragment : BaseDialogFragment() { val FRAGMENT_TAG = "favorite_confirm" - fun show(fm: FragmentManager, accountKey: UserKey? = null, statusId: String, - status: ParcelableStatus?): FavoriteConfirmDialogFragment { + fun show(fm: FragmentManager, accountKey: UserKey, statusId: String, + status: ParcelableStatus? = null): FavoriteConfirmDialogFragment { val f = FavoriteConfirmDialogFragment() f.arguments = Bundle { this[EXTRA_ACCOUNT_KEY] = accountKey diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/RetweetQuoteDialogFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/RetweetQuoteDialogFragment.kt index 38b98312c..267e3da00 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/RetweetQuoteDialogFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/content/RetweetQuoteDialogFragment.kt @@ -19,8 +19,8 @@ package org.mariotaku.twidere.fragment.content -import android.accounts.AccountManager import android.app.Dialog +import android.content.Context import android.content.DialogInterface import android.content.Intent import android.net.Uri @@ -30,15 +30,19 @@ import android.support.annotation.CheckResult import android.support.v4.app.FragmentManager import android.support.v7.app.AlertDialog import android.support.v7.widget.PopupMenu -import android.text.Editable -import android.text.TextWatcher import android.view.Gravity import android.view.View -import android.widget.* +import android.widget.EditText +import android.widget.ImageButton +import android.widget.RelativeLayout +import android.widget.Toast import com.bumptech.glide.Glide import com.twitter.Validator +import nl.komponents.kovenant.Promise +import nl.komponents.kovenant.task import org.mariotaku.ktextension.* import org.mariotaku.library.objectcursor.ObjectCursor +import org.mariotaku.microblog.library.MicroBlog import org.mariotaku.twidere.R import org.mariotaku.twidere.activity.content.RetweetQuoteDialogActivity import org.mariotaku.twidere.adapter.DummyItemAdapter @@ -46,18 +50,19 @@ import org.mariotaku.twidere.annotation.AccountType import org.mariotaku.twidere.constant.IntentConstants.* import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_QUICK_SEND import org.mariotaku.twidere.extension.applyTheme +import org.mariotaku.twidere.extension.model.newMicroBlogInstance import org.mariotaku.twidere.extension.model.textLimit import org.mariotaku.twidere.fragment.BaseDialogFragment import org.mariotaku.twidere.model.* import org.mariotaku.twidere.model.draft.QuoteStatusActionExtras -import org.mariotaku.twidere.model.util.AccountUtils +import org.mariotaku.twidere.model.util.ParcelableStatusUtils import org.mariotaku.twidere.provider.TwidereDataStore.Drafts import org.mariotaku.twidere.service.LengthyOperationsService import org.mariotaku.twidere.util.Analyzer import org.mariotaku.twidere.util.EditTextEnterHandler import org.mariotaku.twidere.util.LinkCreator import org.mariotaku.twidere.util.Utils.isMyRetweet -import org.mariotaku.twidere.view.ColorLabelRelativeLayout +import org.mariotaku.twidere.util.view.SimpleTextWatcher import org.mariotaku.twidere.view.ComposeEditText import org.mariotaku.twidere.view.StatusTextCountView import org.mariotaku.twidere.view.holder.StatusViewHolder @@ -66,46 +71,100 @@ import java.util.* /** * Asks user to retweet/quote a status. */ -class RetweetQuoteDialogFragment : BaseDialogFragment() { +class RetweetQuoteDialogFragment : AbsStatusDialogFragment() { + + override val Dialog.loadProgress: View get() = findViewById(R.id.loadProgress) + override val Dialog.itemContent: View get() = findViewById(R.id.itemContent) + private lateinit var popupMenu: PopupMenu - private val PopupMenu.quoteOriginalStatus get() = menu.isItemChecked(R.id.quote_original_status) - private val Dialog.loadProgress get() = findViewById(R.id.loadProgress) - private val Dialog.itemContent get() = findViewById(R.id.itemContent) as ColorLabelRelativeLayout private val Dialog.textCountView get() = findViewById(R.id.commentTextCount) as StatusTextCountView - private val Dialog.itemMenu get() = findViewById(R.id.itemMenu) as ImageButton - private val Dialog.actionButtons get() = findViewById(R.id.actionButtons) as LinearLayout + private val Dialog.commentContainer get() = findViewById(R.id.commentContainer) as RelativeLayout private val Dialog.editComment get() = findViewById(R.id.editComment) as ComposeEditText private val Dialog.commentMenu get() = findViewById(R.id.commentMenu) as ImageButton - - private val status: ParcelableStatus - get() = arguments.getParcelable(EXTRA_STATUS) - - private val accountKey: UserKey - get() = arguments.getParcelable(EXTRA_ACCOUNT_KEY) ?: status.account_key + private val PopupMenu.quoteOriginalStatus get() = menu.isItemChecked(R.id.quote_original_status) private val text: String? get() = arguments.getString(EXTRA_TEXT) - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val builder = AlertDialog.Builder(context) - val accountKey = this.accountKey - val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true)!! - val status = this.status.apply { - if (account_key != accountKey) { - my_retweet_id = null - } - account_key = details.key - account_color = details.color - } + override fun AlertDialog.Builder.setupAlertDialog() { + setTitle(R.string.title_retweet_quote_confirm) + setView(R.layout.dialog_status_quote_retweet) + setPositiveButton(R.string.action_retweet, null) + setNegativeButton(android.R.string.cancel, null) + setNeutralButton(R.string.action_quote, null) + } - builder.setView(R.layout.dialog_status_quote_retweet) - builder.setTitle(R.string.title_retweet_quote_confirm) - builder.setPositiveButton(R.string.action_retweet, null) - builder.setNegativeButton(android.R.string.cancel, null) - builder.setNeutralButton(R.string.action_quote) { _, _ -> + override fun AlertDialog.onStatusLoaded(details: AccountDetails, status: ParcelableStatus, + savedInstanceState: Bundle?) { + + val adapter = DummyItemAdapter(context, requestManager = Glide.with(this@RetweetQuoteDialogFragment)) + adapter.setShouldShowAccountsColor(true) + val holder = StatusViewHolder(adapter, itemContent) + holder.displayStatus(status = status, displayInReplyTo = false) + + textCountView.maxLength = details.textLimit + + val useQuote = useQuote(!status.user_is_protected, details) + + commentContainer.visibility = if (useQuote) View.VISIBLE else View.GONE + editComment.accountKey = details.key + + val enterHandler = EditTextEnterHandler.attach(editComment, object : EditTextEnterHandler.EnterListener { + override fun shouldCallListener(): Boolean { + return true + } + + override fun onHitEnter(): Boolean { + if (retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM)) { + dismiss() + return true + } + return false + } + }, preferences.getBoolean(KEY_QUICK_SEND)) + enterHandler.addTextChangedListener(object : SimpleTextWatcher { + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + updateTextCount(getDialog(), s, status, details) + } + }) + + popupMenu = PopupMenu(context, commentMenu, Gravity.NO_GRAVITY, + R.attr.actionOverflowMenuStyle, 0).apply { + inflate(R.menu.menu_dialog_comment) + menu.setItemAvailability(R.id.quote_original_status, status.retweet_id != null || status.quoted_id != null) + setOnMenuItemClickListener(PopupMenu.OnMenuItemClickListener { item -> + if (item.isCheckable) { + item.isChecked = !item.isChecked + return@OnMenuItemClickListener true + } + false + }) + } + commentMenu.setOnClickListener { popupMenu.show() } + commentMenu.setOnTouchListener(popupMenu.dragToOpenListener) + commentMenu.visibility = if (popupMenu.menu.hasVisibleItems()) View.VISIBLE else View.GONE + + getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener { + var dismissDialog = false + if (editComment.length() > 0) { + dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM) + } else if (isMyRetweet(status)) { + twitterWrapper.cancelRetweetAsync(details.key, status.id, status.my_retweet_id) + dismissDialog = true + } else if (useQuote(!status.user_is_protected, details)) { + dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM) + } else { + Analyzer.logException(IllegalStateException(status.toString())) + } + if (dismissDialog) { + dismiss() + } + } + getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener { val intent = Intent(INTENT_ACTION_QUOTE) val menu = popupMenu.menu val quoteOriginalStatus = menu.findItem(R.id.quote_original_status) @@ -114,96 +173,12 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() { startActivity(intent) } - val dialog = builder.create() - dialog.setOnShowListener { dialog -> - dialog as AlertDialog - dialog.applyTheme() - - val adapter = DummyItemAdapter(context, requestManager = Glide.with(this)) - adapter.setShouldShowAccountsColor(true) - val holder = StatusViewHolder(adapter, dialog.itemContent) - holder.displayStatus(status = status, displayInReplyTo = false) - - dialog.textCountView.maxLength = details.textLimit - - dialog.loadProgress.visibility = View.GONE - dialog.itemMenu.visibility = View.GONE - dialog.actionButtons.visibility = View.GONE - dialog.itemContent.isFocusable = false - val useQuote = useQuote(!status.user_is_protected, details) - - dialog.commentContainer.visibility = if (useQuote) View.VISIBLE else View.GONE - dialog.editComment.accountKey = details.key - - val sendByEnter = preferences.getBoolean(KEY_QUICK_SEND) - val enterHandler = EditTextEnterHandler.attach(dialog.editComment, object : EditTextEnterHandler.EnterListener { - override fun shouldCallListener(): Boolean { - return true - } - - override fun onHitEnter(): Boolean { - if (retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM)) { - dismiss() - return true - } - return false - } - }, sendByEnter) - enterHandler.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { - - } - - override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { - updateTextCount(getDialog(), s, status, details) - } - - override fun afterTextChanged(s: Editable) { - - } - }) - - popupMenu = PopupMenu(context, dialog.commentMenu, Gravity.NO_GRAVITY, - R.attr.actionOverflowMenuStyle, 0).apply { - inflate(R.menu.menu_dialog_comment) - menu.setItemAvailability(R.id.quote_original_status, status.retweet_id != null || status.quoted_id != null) - setOnMenuItemClickListener(PopupMenu.OnMenuItemClickListener { item -> - if (item.isCheckable) { - item.isChecked = !item.isChecked - return@OnMenuItemClickListener true - } - false - }) - } - dialog.commentMenu.setOnClickListener { popupMenu.show() } - dialog.commentMenu.setOnTouchListener(popupMenu.dragToOpenListener) - dialog.commentMenu.visibility = if (popupMenu.menu.hasVisibleItems()) View.VISIBLE else View.GONE - - dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener { - var dismissDialog = false - if (dialog.editComment.length() > 0) { - dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM) - } else if (isMyRetweet(status)) { - twitterWrapper.cancelRetweetAsync(details.key, status.id, status.my_retweet_id) - dismissDialog = true - } else if (useQuote(!status.user_is_protected, details)) { - dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM) - } else { - Analyzer.logException(IllegalStateException(status.toString())) - } - if (dismissDialog) { - dismiss() - } - } - - if (savedInstanceState == null) { - dialog.editComment.setText(text) - } - dialog.editComment.setSelection(dialog.editComment.length()) - - updateTextCount(dialog, dialog.editComment.text, status, details) + if (savedInstanceState == null) { + editComment.setText(text) } - return dialog + editComment.setSelection(editComment.length()) + + updateTextCount(dialog, editComment.text, status, details) } override fun onCancel(dialog: DialogInterface) { @@ -311,7 +286,6 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() { return preCondition || AccountType.FANFOU == account.type } - private fun Dialog.saveToDrafts() { val text = dialog.editComment.text.toString() val draft = Draft() @@ -391,8 +365,9 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() { val FRAGMENT_TAG = "retweet_quote" private val SHOW_PROTECTED_CONFIRM = java.lang.Boolean.parseBoolean("false") - fun show(fm: FragmentManager, accountKey: UserKey? = null, statusId: String, - status: ParcelableStatus?, text: String? = null): RetweetQuoteDialogFragment { + fun show(fm: FragmentManager, accountKey: UserKey, statusId: String, + status: ParcelableStatus? = null, text: String? = null): + RetweetQuoteDialogFragment { val f = RetweetQuoteDialogFragment() f.arguments = Bundle { this[EXTRA_ACCOUNT_KEY] = accountKey @@ -403,5 +378,26 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() { f.show(fm, FRAGMENT_TAG) return f } + + fun showStatus(context: Context, details: AccountDetails, statusId: String, + status: ParcelableStatus?): Promise { + if (status != null) { + status.apply { + if (account_key != details.key) { + my_retweet_id = null + } + account_key = details.key + account_color = details.color + } + return Promise.ofSuccess(status) + } + val microBlog = details.newMicroBlogInstance(context, MicroBlog::class.java) + val profileImageSize = context.getString(R.string.profile_image_size) + return task { + ParcelableStatusUtils.fromStatus(microBlog.showStatus(statusId), details.key, + details.type, profileImageSize = profileImageSize) + } + } + } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt index 2bfb69a2b..3ede523f2 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt @@ -17,6 +17,7 @@ import org.mariotaku.twidere.R import org.mariotaku.twidere.TwidereConstants.* import org.mariotaku.twidere.activity.MediaViewerActivity import org.mariotaku.twidere.annotation.Referral +import org.mariotaku.twidere.constant.IntentConstants import org.mariotaku.twidere.fragment.SensitiveContentWarningDialogFragment import org.mariotaku.twidere.model.* import org.mariotaku.twidere.model.util.ParcelableLocationUtils @@ -77,13 +78,15 @@ object IntentUtils { } fun userProfile(accountKey: UserKey?, userKey: UserKey?, screenName: String?, - @Referral referral: String? = null, profileUrl: String? = null): Intent { + @Referral referral: String? = null, profileUrl: String? = null, + accountHost: String? = accountKey?.host ?: userKey?.host): Intent { val uri = LinkCreator.getTwidereUserLink(accountKey, userKey, screenName) val intent = Intent(Intent.ACTION_VIEW, uri) if (referral != null) { intent.putExtra(EXTRA_REFERRAL, referral) } intent.putExtra(EXTRA_PROFILE_URL, profileUrl) + intent.putExtra(EXTRA_ACCOUNT_HOST, accountHost) return intent } diff --git a/twidere/src/main/res/layout/dialog_status_favorite_confirm.xml b/twidere/src/main/res/layout/dialog_status_favorite_confirm.xml index 0560b0351..3639ecd56 100644 --- a/twidere/src/main/res/layout/dialog_status_favorite_confirm.xml +++ b/twidere/src/main/res/layout/dialog_status_favorite_confirm.xml @@ -39,7 +39,7 @@ android:id="@+id/loadProgress" android:layout_width="match_parent" android:layout_height="wrap_content" - android:minHeight="96dp"> + android:minHeight="@dimen/element_size_mlarge"> + android:minHeight="@dimen/element_size_mlarge">