parent
8f7fd2b330
commit
632db4ad0c
|
@ -31,6 +31,10 @@ import android.support.annotation.Nullable;
|
||||||
import org.mariotaku.twidere.constant.IntentConstants;
|
import org.mariotaku.twidere.constant.IntentConstants;
|
||||||
import org.mariotaku.twidere.util.ServiceUtils.ServiceToken;
|
import org.mariotaku.twidere.util.ServiceUtils.ServiceToken;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
|
|
||||||
public abstract class AbsServiceInterface<I extends IInterface> implements IInterface {
|
public abstract class AbsServiceInterface<I extends IInterface> implements IInterface {
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
@ -40,27 +44,10 @@ public abstract class AbsServiceInterface<I extends IInterface> implements IInte
|
||||||
private I mIInterface;
|
private I mIInterface;
|
||||||
|
|
||||||
private ServiceToken mToken;
|
private ServiceToken mToken;
|
||||||
private boolean mDisconnected;
|
|
||||||
|
|
||||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceConnected(final ComponentName service, final IBinder obj) {
|
|
||||||
mIInterface = AbsServiceInterface.this.onServiceConnected(service, obj);
|
|
||||||
mDisconnected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceDisconnected(final ComponentName service) {
|
|
||||||
mIInterface = null;
|
|
||||||
mDisconnected = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected abstract I onServiceConnected(ComponentName service, IBinder obj);
|
protected abstract I onServiceConnected(ComponentName service, IBinder obj);
|
||||||
|
|
||||||
protected AbsServiceInterface(final Context context, final String componentName, @Nullable final Bundle metaData) {
|
protected AbsServiceInterface(final Context context, final String componentName, @Nullable final Bundle metaData) {
|
||||||
mDisconnected = true;
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mShortenerName = componentName;
|
mShortenerName = componentName;
|
||||||
mMetaData = metaData;
|
mMetaData = metaData;
|
||||||
|
@ -86,19 +73,38 @@ public abstract class AbsServiceInterface<I extends IInterface> implements IInte
|
||||||
final Intent intent = new Intent(IntentConstants.INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
final Intent intent = new Intent(IntentConstants.INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
||||||
final ComponentName component = ComponentName.unflattenFromString(mShortenerName);
|
final ComponentName component = ComponentName.unflattenFromString(mShortenerName);
|
||||||
intent.setComponent(component);
|
intent.setComponent(component);
|
||||||
mDisconnected = true;
|
final FutureTask<Boolean> futureTask = new FutureTask<>(new Callable<Boolean>() {
|
||||||
mToken = ServiceUtils.bindToService(mContext, intent, mConnection);
|
@Override
|
||||||
if (mToken == null) return false;
|
public Boolean call() throws Exception {
|
||||||
mDisconnected = false;
|
return mIInterface != null;
|
||||||
while (mIInterface == null && !mDisconnected) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(50L);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Ignore
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
mToken = ServiceUtils.bindToService(mContext, intent, new ServiceConnection() {
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(final ComponentName name, final IBinder obj) {
|
||||||
|
mIInterface = AbsServiceInterface.this.onServiceConnected(name, obj);
|
||||||
|
if (!futureTask.isDone() && !futureTask.isCancelled()) {
|
||||||
|
futureTask.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(final ComponentName name) {
|
||||||
|
mIInterface = null;
|
||||||
|
if (!futureTask.isDone() && !futureTask.isCancelled()) {
|
||||||
|
futureTask.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (mToken == null) return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return futureTask.get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return false;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void checkService(CheckServiceAction action) throws CheckServiceException {
|
public final void checkService(CheckServiceAction action) throws CheckServiceException {
|
||||||
|
|
|
@ -49,7 +49,7 @@ public final class ServiceUtils {
|
||||||
return new ServiceToken(cw);
|
return new ServiceToken(cw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.e(LOGTAG, "Failed to bind to service");
|
DebugLog.w(LOGTAG, "Failed to bind to service", null);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,7 @@ class AccountSelectorActivity : BaseActivity(), OnItemClickListener {
|
||||||
}
|
}
|
||||||
val data = Intent()
|
val data = Intent()
|
||||||
data.putExtra(EXTRA_IDS, checkedIds)
|
data.putExtra(EXTRA_IDS, checkedIds)
|
||||||
|
data.putExtra(EXTRA_EXTRAS, intent.getBundleExtra(EXTRA_EXTRAS))
|
||||||
setResult(Activity.RESULT_OK, data)
|
setResult(Activity.RESULT_OK, data)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
@ -143,6 +144,7 @@ class AccountSelectorActivity : BaseActivity(), OnItemClickListener {
|
||||||
val data = Intent()
|
val data = Intent()
|
||||||
data.putExtra(EXTRA_ID, account.key.id)
|
data.putExtra(EXTRA_ID, account.key.id)
|
||||||
data.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
data.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
||||||
|
data.putExtra(EXTRA_EXTRAS, intent.getBundleExtra(EXTRA_EXTRAS))
|
||||||
|
|
||||||
val startIntent = startIntent
|
val startIntent = startIntent
|
||||||
if (startIntent != null) {
|
if (startIntent != null) {
|
||||||
|
|
|
@ -356,6 +356,8 @@ class ParcelableActivitiesAdapter(
|
||||||
|
|
||||||
fun onStatusActionClick(holder: IStatusViewHolder, id: Int, position: Int)
|
fun onStatusActionClick(holder: IStatusViewHolder, id: Int, position: Int)
|
||||||
|
|
||||||
|
fun onStatusActionLongClick(holder: IStatusViewHolder, id: Int, position: Int): Boolean
|
||||||
|
|
||||||
fun onStatusMenuClick(holder: IStatusViewHolder, menuView: View, position: Int)
|
fun onStatusMenuClick(holder: IStatusViewHolder, menuView: View, position: Int)
|
||||||
|
|
||||||
fun onMediaClick(holder: IStatusViewHolder, view: View, media: ParcelableMedia, position: Int)
|
fun onMediaClick(holder: IStatusViewHolder, view: View, media: ParcelableMedia, position: Int)
|
||||||
|
@ -398,8 +400,13 @@ class ParcelableActivitiesAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemActionClick(holder: RecyclerView.ViewHolder, id: Int, position: Int) {
|
override fun onItemActionClick(holder: RecyclerView.ViewHolder, id: Int, position: Int) {
|
||||||
val adapter = adapterRef.get() ?: return
|
val listener = adapterRef.get()?.activityAdapterListener ?: return
|
||||||
adapter.activityAdapterListener?.onStatusActionClick(holder as IStatusViewHolder, id, position)
|
listener.onStatusActionClick(holder as IStatusViewHolder, id, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemActionLongClick(holder: RecyclerView.ViewHolder, id: Int, position: Int): Boolean {
|
||||||
|
val listener = adapterRef.get()?.activityAdapterListener ?: return false
|
||||||
|
return listener.onStatusActionLongClick(holder as IStatusViewHolder, id, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStatusLongClick(holder: IStatusViewHolder, position: Int): Boolean {
|
override fun onStatusLongClick(holder: IStatusViewHolder, position: Int): Boolean {
|
||||||
|
|
|
@ -28,5 +28,7 @@ import android.view.View
|
||||||
interface ContentCardClickListener {
|
interface ContentCardClickListener {
|
||||||
fun onItemActionClick(holder: ViewHolder, id: Int, position: Int) {}
|
fun onItemActionClick(holder: ViewHolder, id: Int, position: Int) {}
|
||||||
|
|
||||||
|
fun onItemActionLongClick(holder: ViewHolder, id: Int, position: Int): Boolean = false
|
||||||
|
|
||||||
fun onItemMenuClick(holder: ViewHolder, menuView: View, position: Int) {}
|
fun onItemMenuClick(holder: ViewHolder, menuView: View, position: Int) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.mariotaku.twidere.fragment
|
package org.mariotaku.twidere.fragment
|
||||||
|
|
||||||
import android.accounts.AccountManager
|
import android.accounts.AccountManager
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
@ -49,8 +50,12 @@ import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.Companion.ITEM_
|
||||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration
|
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration
|
||||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
||||||
import org.mariotaku.twidere.annotation.ReadPositionTag
|
import org.mariotaku.twidere.annotation.ReadPositionTag
|
||||||
import org.mariotaku.twidere.constant.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
||||||
|
import org.mariotaku.twidere.constant.displaySensitiveContentsKey
|
||||||
|
import org.mariotaku.twidere.constant.newDocumentApiKey
|
||||||
|
import org.mariotaku.twidere.constant.readFromBottomKey
|
||||||
|
import org.mariotaku.twidere.constant.rememberPositionKey
|
||||||
import org.mariotaku.twidere.extension.model.getAccountType
|
import org.mariotaku.twidere.extension.model.getAccountType
|
||||||
import org.mariotaku.twidere.fragment.AbsStatusesFragment.DefaultOnLikedListener
|
import org.mariotaku.twidere.fragment.AbsStatusesFragment.DefaultOnLikedListener
|
||||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
||||||
|
@ -101,11 +106,20 @@ abstract class AbsActivitiesFragment protected constructor() :
|
||||||
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(adapter.mediaLoader.imageLoader, false, true)
|
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(adapter.mediaLoader.imageLoader, false, true)
|
||||||
|
|
||||||
val loaderArgs = Bundle(arguments)
|
val loaderArgs = Bundle(arguments)
|
||||||
loaderArgs.putBoolean(IntentConstants.EXTRA_FROM_USER, true)
|
loaderArgs.putBoolean(EXTRA_FROM_USER, true)
|
||||||
loaderManager.initLoader(0, loaderArgs, this)
|
loaderManager.initLoader(0, loaderArgs, this)
|
||||||
showProgress()
|
showProgress()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
when (requestCode) {
|
||||||
|
AbsStatusesFragment.REQUEST_FAVORITE_SELECT_ACCOUNT,
|
||||||
|
AbsStatusesFragment.REQUEST_RETWEET_SELECT_ACCOUNT -> {
|
||||||
|
AbsStatusesFragment.handleActionActivityResult(this, requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract fun getActivities(param: RefreshTaskParam): Boolean
|
abstract fun getActivities(param: RefreshTaskParam): Boolean
|
||||||
|
|
||||||
override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler, keyCode: Int, event: KeyEvent, metaState: Int): Boolean {
|
override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler, keyCode: Int, event: KeyEvent, metaState: Int): Boolean {
|
||||||
|
@ -133,8 +147,8 @@ abstract class AbsActivitiesFragment protected constructor() :
|
||||||
if (action == null) return false
|
if (action == null) return false
|
||||||
when (action) {
|
when (action) {
|
||||||
ACTION_STATUS_REPLY -> {
|
ACTION_STATUS_REPLY -> {
|
||||||
val intent = Intent(IntentConstants.INTENT_ACTION_REPLY)
|
val intent = Intent(INTENT_ACTION_REPLY)
|
||||||
intent.putExtra(IntentConstants.EXTRA_STATUS, status)
|
intent.putExtra(EXTRA_STATUS, status)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -185,8 +199,8 @@ abstract class AbsActivitiesFragment protected constructor() :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateLoader(id: Int, args: Bundle): Loader<List<ParcelableActivity>> {
|
override fun onCreateLoader(id: Int, args: Bundle): Loader<List<ParcelableActivity>> {
|
||||||
val fromUser = args.getBoolean(IntentConstants.EXTRA_FROM_USER)
|
val fromUser = args.getBoolean(EXTRA_FROM_USER)
|
||||||
args.remove(IntentConstants.EXTRA_FROM_USER)
|
args.remove(EXTRA_FROM_USER)
|
||||||
return onCreateActivitiesLoader(activity, args, fromUser)
|
return onCreateActivitiesLoader(activity, args, fromUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,9 +331,9 @@ abstract class AbsActivitiesFragment protected constructor() :
|
||||||
val activity = activity
|
val activity = activity
|
||||||
when (id) {
|
when (id) {
|
||||||
R.id.reply -> {
|
R.id.reply -> {
|
||||||
val intent = Intent(IntentConstants.INTENT_ACTION_REPLY)
|
val intent = Intent(INTENT_ACTION_REPLY)
|
||||||
intent.`package` = activity.packageName
|
intent.`package` = activity.packageName
|
||||||
intent.putExtra(IntentConstants.EXTRA_STATUS, status)
|
intent.putExtra(EXTRA_STATUS, status)
|
||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
R.id.retweet -> {
|
R.id.retweet -> {
|
||||||
|
@ -335,6 +349,11 @@ abstract class AbsActivitiesFragment protected constructor() :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStatusActionLongClick(holder: IStatusViewHolder, id: Int, position: Int): Boolean {
|
||||||
|
val status = getActivityStatus(position) ?: return false
|
||||||
|
return AbsStatusesFragment.handleActionLongClick(this, status, adapter.getItemId(position), id)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onActivityClick(holder: ActivityTitleSummaryViewHolder, position: Int) {
|
override fun onActivityClick(holder: ActivityTitleSummaryViewHolder, position: Int) {
|
||||||
val activity = adapter.getActivity(position) ?: return
|
val activity = adapter.getActivity(position) ?: return
|
||||||
val list = ArrayList<Parcelable>()
|
val list = ArrayList<Parcelable>()
|
||||||
|
|
|
@ -20,10 +20,12 @@
|
||||||
package org.mariotaku.twidere.fragment
|
package org.mariotaku.twidere.fragment
|
||||||
|
|
||||||
import android.accounts.AccountManager
|
import android.accounts.AccountManager
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.support.v4.app.Fragment
|
||||||
import android.support.v4.app.FragmentManager
|
import android.support.v4.app.FragmentManager
|
||||||
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
||||||
import android.support.v4.content.Loader
|
import android.support.v4.content.Loader
|
||||||
|
@ -36,22 +38,18 @@ import edu.tsinghua.hotmobi.HotMobiLogger
|
||||||
import edu.tsinghua.hotmobi.model.MediaEvent
|
import edu.tsinghua.hotmobi.model.MediaEvent
|
||||||
import kotlinx.android.synthetic.main.fragment_content_recyclerview.*
|
import kotlinx.android.synthetic.main.fragment_content_recyclerview.*
|
||||||
import org.mariotaku.kpreferences.get
|
import org.mariotaku.kpreferences.get
|
||||||
import org.mariotaku.ktextension.coerceInOr
|
import org.mariotaku.ktextension.*
|
||||||
import org.mariotaku.ktextension.isNullOrEmpty
|
|
||||||
import org.mariotaku.ktextension.rangeOfSize
|
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.TwidereConstants
|
import org.mariotaku.twidere.TwidereConstants
|
||||||
|
import org.mariotaku.twidere.activity.AccountSelectorActivity
|
||||||
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter
|
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter
|
||||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration
|
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration
|
||||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
||||||
import org.mariotaku.twidere.annotation.ReadPositionTag
|
import org.mariotaku.twidere.annotation.ReadPositionTag
|
||||||
import org.mariotaku.twidere.annotation.Referral
|
import org.mariotaku.twidere.annotation.Referral
|
||||||
|
import org.mariotaku.twidere.constant.*
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
||||||
import org.mariotaku.twidere.constant.displaySensitiveContentsKey
|
|
||||||
import org.mariotaku.twidere.constant.newDocumentApiKey
|
|
||||||
import org.mariotaku.twidere.constant.readFromBottomKey
|
|
||||||
import org.mariotaku.twidere.constant.rememberPositionKey
|
|
||||||
import org.mariotaku.twidere.extension.model.getAccountType
|
import org.mariotaku.twidere.extension.model.getAccountType
|
||||||
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
|
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
|
||||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
||||||
|
@ -70,8 +68,7 @@ import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 14/11/5.
|
* Created by mariotaku on 14/11/5.
|
||||||
*/
|
*/
|
||||||
abstract class AbsStatusesFragment protected constructor() :
|
abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<ParcelableStatusesAdapter>(),
|
||||||
AbsContentListRecyclerViewFragment<ParcelableStatusesAdapter>(),
|
|
||||||
LoaderCallbacks<List<ParcelableStatus>?>, IStatusViewHolder.StatusClickListener,
|
LoaderCallbacks<List<ParcelableStatus>?>, IStatusViewHolder.StatusClickListener,
|
||||||
KeyboardShortcutCallback {
|
KeyboardShortcutCallback {
|
||||||
|
|
||||||
|
@ -163,6 +160,14 @@ abstract class AbsStatusesFragment protected constructor() :
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
when (requestCode) {
|
||||||
|
REQUEST_FAVORITE_SELECT_ACCOUNT, REQUEST_RETWEET_SELECT_ACCOUNT -> {
|
||||||
|
handleActionActivityResult(this, requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract fun getStatuses(param: RefreshTaskParam): Boolean
|
abstract fun getStatuses(param: RefreshTaskParam): Boolean
|
||||||
|
|
||||||
override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler, keyCode: Int, event: KeyEvent, metaState: Int): Boolean {
|
override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler, keyCode: Int, event: KeyEvent, metaState: Int): Boolean {
|
||||||
|
@ -370,7 +375,12 @@ abstract class AbsStatusesFragment protected constructor() :
|
||||||
|
|
||||||
override fun onItemActionClick(holder: RecyclerView.ViewHolder, id: Int, position: Int) {
|
override fun onItemActionClick(holder: RecyclerView.ViewHolder, id: Int, position: Int) {
|
||||||
val status = adapter.getStatus(position) ?: return
|
val status = adapter.getStatus(position) ?: return
|
||||||
handleStatusActionClick(context, fragmentManager, twitterWrapper, holder as StatusViewHolder, status, id)
|
handleActionClick(context, fragmentManager, twitterWrapper, holder as StatusViewHolder, status, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemActionLongClick(holder: RecyclerView.ViewHolder, id: Int, position: Int): Boolean {
|
||||||
|
val status = adapter.getStatus(position) ?: return false
|
||||||
|
return handleActionLongClick(this, status, adapter.getItemId(position), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createItemDecoration(context: Context, recyclerView: RecyclerView, layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? {
|
override fun createItemDecoration(context: Context, recyclerView: RecyclerView, layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? {
|
||||||
|
@ -508,12 +518,13 @@ abstract class AbsStatusesFragment protected constructor() :
|
||||||
|
|
||||||
class DefaultOnLikedListener(
|
class DefaultOnLikedListener(
|
||||||
private val twitter: AsyncTwitterWrapper,
|
private val twitter: AsyncTwitterWrapper,
|
||||||
private val status: ParcelableStatus
|
private val status: ParcelableStatus,
|
||||||
|
private val accountKey: UserKey? = null
|
||||||
) : LikeAnimationDrawable.OnLikedListener {
|
) : LikeAnimationDrawable.OnLikedListener {
|
||||||
|
|
||||||
override fun onLiked(): Boolean {
|
override fun onLiked(): Boolean {
|
||||||
if (status.is_favorite) return false
|
if (status.is_favorite) return false
|
||||||
twitter.createFavoriteAsync(status.account_key, status)
|
twitter.createFavoriteAsync(accountKey ?: status.account_key, status)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -533,11 +544,11 @@ abstract class AbsStatusesFragment protected constructor() :
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun handleStatusActionClick(context: Context, fm: FragmentManager,
|
const val REQUEST_FAVORITE_SELECT_ACCOUNT = 101
|
||||||
twitter: AsyncTwitterWrapper?, holder: StatusViewHolder,
|
const val REQUEST_RETWEET_SELECT_ACCOUNT = 102
|
||||||
status: ParcelableStatus?, id: Int) {
|
|
||||||
|
|
||||||
if (status == null) return
|
fun handleActionClick(context: Context, fm: FragmentManager, twitter: AsyncTwitterWrapper?,
|
||||||
|
holder: StatusViewHolder, status: ParcelableStatus, id: Int) {
|
||||||
when (id) {
|
when (id) {
|
||||||
R.id.reply -> {
|
R.id.reply -> {
|
||||||
val intent = Intent(INTENT_ACTION_REPLY)
|
val intent = Intent(INTENT_ACTION_REPLY)
|
||||||
|
@ -553,11 +564,58 @@ abstract class AbsStatusesFragment protected constructor() :
|
||||||
if (status.is_favorite) {
|
if (status.is_favorite) {
|
||||||
twitter.destroyFavoriteAsync(status.account_key, status.id)
|
twitter.destroyFavoriteAsync(status.account_key, status.id)
|
||||||
} else {
|
} else {
|
||||||
holder.playLikeAnimation(DefaultOnLikedListener(twitter,
|
holder.playLikeAnimation(DefaultOnLikedListener(twitter, status))
|
||||||
status))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun handleActionLongClick(fragment: Fragment, status: ParcelableStatus, itemId: Long, id: Int): Boolean {
|
||||||
|
when (id) {
|
||||||
|
R.id.favorite -> {
|
||||||
|
val intent = selectAccountIntent(fragment.context, status, itemId)
|
||||||
|
fragment.startActivityForResult(intent, REQUEST_FAVORITE_SELECT_ACCOUNT)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
R.id.retweet -> {
|
||||||
|
val intent = selectAccountIntent(fragment.context, status, itemId)
|
||||||
|
fragment.startActivityForResult(intent, REQUEST_RETWEET_SELECT_ACCOUNT)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleActionActivityResult(fragment: BaseFragment, requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
when (requestCode) {
|
||||||
|
AbsStatusesFragment.REQUEST_FAVORITE_SELECT_ACCOUNT -> {
|
||||||
|
if (resultCode != Activity.RESULT_OK || data == null) return
|
||||||
|
val accountKey = data.getParcelableExtra<UserKey>(IntentConstants.EXTRA_ACCOUNT_KEY)
|
||||||
|
val extras = data.getBundleExtra(IntentConstants.EXTRA_EXTRAS)
|
||||||
|
val status = extras.getParcelable<ParcelableStatus>(IntentConstants.EXTRA_STATUS)
|
||||||
|
fragment.twitterWrapper.createFavoriteAsync(accountKey, status)
|
||||||
|
}
|
||||||
|
AbsStatusesFragment.REQUEST_RETWEET_SELECT_ACCOUNT -> {
|
||||||
|
if (resultCode != Activity.RESULT_OK || data == null) return
|
||||||
|
val accountKey = data.getParcelableExtra<UserKey>(IntentConstants.EXTRA_ACCOUNT_KEY)
|
||||||
|
val extras = data.getBundleExtra(IntentConstants.EXTRA_EXTRAS)
|
||||||
|
val status = extras.getParcelable<ParcelableStatus>(IntentConstants.EXTRA_STATUS)
|
||||||
|
RetweetQuoteDialogFragment.show(fragment.childFragmentManager, status, accountKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun selectAccountIntent(context: Context, status: ParcelableStatus, itemId: Long): Intent {
|
||||||
|
val intent = Intent(context, AccountSelectorActivity::class.java)
|
||||||
|
intent.putExtra(EXTRA_SELECT_ONLY_ITEM_AUTOMATICALLY, true)
|
||||||
|
intent.putExtra(EXTRA_ACCOUNT_HOST, status.account_key.host)
|
||||||
|
intent.putExtra(EXTRA_SINGLE_SELECTION, true)
|
||||||
|
intent.putExtra(EXTRA_EXTRAS, Bundle {
|
||||||
|
this[EXTRA_STATUS] = status
|
||||||
|
this[EXTRA_ID] = itemId
|
||||||
|
})
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ class ExtensionsListFragment : AbsContentListViewFragment<ExtensionsAdapter>(),
|
||||||
inflater.inflate(R.menu.action_extension, menu)
|
inflater.inflate(R.menu.action_extension, menu)
|
||||||
val adapterMenuInfo = menuInfo as AdapterContextMenuInfo
|
val adapterMenuInfo = menuInfo as AdapterContextMenuInfo
|
||||||
val extensionInfo = adapter.getItem(adapterMenuInfo.position)
|
val extensionInfo = adapter.getItem(adapterMenuInfo.position)
|
||||||
if (extensionInfo.pname != null && extensionInfo.settings != null) {
|
if (extensionInfo.settings != null) {
|
||||||
val intent = Intent(IntentConstants.INTENT_ACTION_EXTENSION_SETTINGS)
|
val intent = Intent(IntentConstants.INTENT_ACTION_EXTENSION_SETTINGS)
|
||||||
intent.setClassName(extensionInfo.pname, extensionInfo.settings)
|
intent.setClassName(extensionInfo.pname, extensionInfo.settings)
|
||||||
menu.setItemAvailability(R.id.settings, packageManager!!.queryIntentActivities(intent, 0).size == 1)
|
menu.setItemAvailability(R.id.settings, packageManager!!.queryIntentActivities(intent, 0).size == 1)
|
||||||
|
|
|
@ -62,10 +62,16 @@ class ItemsListFragment : AbsContentListRecyclerViewFragment<VariousItemsAdapter
|
||||||
|
|
||||||
override fun onItemActionClick(holder: RecyclerView.ViewHolder, id: Int, position: Int) {
|
override fun onItemActionClick(holder: RecyclerView.ViewHolder, id: Int, position: Int) {
|
||||||
val status = dummyItemAdapter.getStatus(position) ?: return
|
val status = dummyItemAdapter.getStatus(position) ?: return
|
||||||
AbsStatusesFragment.handleStatusActionClick(context, fragmentManager,
|
AbsStatusesFragment.handleActionClick(context, fragmentManager,
|
||||||
twitterWrapper, holder as StatusViewHolder, status, id)
|
twitterWrapper, holder as StatusViewHolder, status, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onItemActionLongClick(holder: RecyclerView.ViewHolder, id: Int, position: Int): Boolean {
|
||||||
|
val status = dummyItemAdapter.getStatus(position) ?: return false
|
||||||
|
return AbsStatusesFragment.handleActionLongClick(this@ItemsListFragment, status,
|
||||||
|
adapter.getItemId(position), id)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onItemMenuClick(holder: RecyclerView.ViewHolder, menuView: View, position: Int) {
|
override fun onItemMenuClick(holder: RecyclerView.ViewHolder, menuView: View, position: Int) {
|
||||||
if (activity == null) return
|
if (activity == null) return
|
||||||
val view = layoutManager.findViewByPosition(position) ?: return
|
val view = layoutManager.findViewByPosition(position) ?: return
|
||||||
|
@ -101,6 +107,15 @@ class ItemsListFragment : AbsContentListRecyclerViewFragment<VariousItemsAdapter
|
||||||
return adapter
|
return adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
when (requestCode) {
|
||||||
|
AbsStatusesFragment.REQUEST_FAVORITE_SELECT_ACCOUNT,
|
||||||
|
AbsStatusesFragment.REQUEST_RETWEET_SELECT_ACCOUNT -> {
|
||||||
|
AbsStatusesFragment.handleActionActivityResult(this, requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<*>?> {
|
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<*>?> {
|
||||||
return ItemsLoader(context, arguments)
|
return ItemsLoader(context, arguments)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import com.twitter.Validator
|
import com.twitter.Validator
|
||||||
|
import org.mariotaku.ktextension.Bundle
|
||||||
|
import org.mariotaku.ktextension.set
|
||||||
import org.mariotaku.ktextension.setItemAvailability
|
import org.mariotaku.ktextension.setItemAvailability
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.adapter.DummyItemAdapter
|
import org.mariotaku.twidere.adapter.DummyItemAdapter
|
||||||
|
@ -42,10 +44,7 @@ import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_QUICK_SEND
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_QUICK_SEND
|
||||||
import org.mariotaku.twidere.extension.applyTheme
|
import org.mariotaku.twidere.extension.applyTheme
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.*
|
||||||
import org.mariotaku.twidere.model.Draft
|
|
||||||
import org.mariotaku.twidere.model.ParcelableStatus
|
|
||||||
import org.mariotaku.twidere.model.ParcelableStatusUpdate
|
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.service.LengthyOperationsService
|
import org.mariotaku.twidere.service.LengthyOperationsService
|
||||||
import org.mariotaku.twidere.util.Analyzer
|
import org.mariotaku.twidere.util.Analyzer
|
||||||
|
@ -62,9 +61,9 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val builder = AlertDialog.Builder(context)
|
val builder = AlertDialog.Builder(context)
|
||||||
val context = builder.context
|
val status = this.status
|
||||||
val status = status!!
|
val accountKey = this.accountKey
|
||||||
val details = AccountUtils.getAccountDetails(AccountManager.get(context), status.account_key, true)!!
|
val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true)!!
|
||||||
|
|
||||||
builder.setView(R.layout.dialog_status_quote_retweet)
|
builder.setView(R.layout.dialog_status_quote_retweet)
|
||||||
builder.setTitle(R.string.retweet_quote_confirm_title)
|
builder.setTitle(R.string.retweet_quote_confirm_title)
|
||||||
|
@ -104,7 +103,7 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
|
||||||
val useQuote = useQuote(!status.user_is_protected, details)
|
val useQuote = useQuote(!status.user_is_protected, details)
|
||||||
|
|
||||||
commentContainer.visibility = if (useQuote) View.VISIBLE else View.GONE
|
commentContainer.visibility = if (useQuote) View.VISIBLE else View.GONE
|
||||||
editComment.accountKey = (status.account_key)
|
editComment.accountKey = details.key
|
||||||
|
|
||||||
val sendByEnter = preferences.getBoolean(KEY_QUICK_SEND)
|
val sendByEnter = preferences.getBoolean(KEY_QUICK_SEND)
|
||||||
val enterHandler = EditTextEnterHandler.attach(editComment, object : EditTextEnterHandler.EnterListener {
|
val enterHandler = EditTextEnterHandler.attach(editComment, object : EditTextEnterHandler.EnterListener {
|
||||||
|
@ -155,7 +154,7 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
|
||||||
if (editComment.length() > 0) {
|
if (editComment.length() > 0) {
|
||||||
dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM)
|
dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM)
|
||||||
} else if (isMyRetweet(status)) {
|
} else if (isMyRetweet(status)) {
|
||||||
twitterWrapper.cancelRetweetAsync(status.account_key, status.id, status.my_retweet_id)
|
twitterWrapper.cancelRetweetAsync(details.key, status.id, status.my_retweet_id)
|
||||||
dismissDialog = true
|
dismissDialog = true
|
||||||
} else if (useQuote(!status.user_is_protected, details)) {
|
} else if (useQuote(!status.user_is_protected, details)) {
|
||||||
dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM)
|
dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM)
|
||||||
|
@ -192,12 +191,11 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
|
||||||
textCountView.textCount = validator.getTweetLength(s.toString())
|
textCountView.textCount = validator.getTweetLength(s.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val status: ParcelableStatus?
|
private val status: ParcelableStatus
|
||||||
get() {
|
get() = arguments.getParcelable<ParcelableStatus>(EXTRA_STATUS)
|
||||||
val args = arguments
|
|
||||||
if (!args.containsKey(EXTRA_STATUS)) return null
|
private val accountKey: UserKey
|
||||||
return args.getParcelable<ParcelableStatus>(EXTRA_STATUS)
|
get() = arguments.getParcelable(EXTRA_ACCOUNT_KEY) ?: status.account_key
|
||||||
}
|
|
||||||
|
|
||||||
@CheckResult
|
@CheckResult
|
||||||
private fun retweetOrQuote(account: AccountDetails, status: ParcelableStatus,
|
private fun retweetOrQuote(account: AccountDetails, status: ParcelableStatus,
|
||||||
|
@ -252,7 +250,7 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
|
||||||
update.is_possibly_sensitive = status.is_possibly_sensitive
|
update.is_possibly_sensitive = status.is_possibly_sensitive
|
||||||
LengthyOperationsService.updateStatusesAsync(context, Draft.Action.QUOTE, update)
|
LengthyOperationsService.updateStatusesAsync(context, Draft.Action.QUOTE, update)
|
||||||
} else {
|
} else {
|
||||||
twitter.retweetStatusAsync(status.account_key, status)
|
twitter.retweetStatusAsync(account.key, status)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -314,11 +312,12 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
|
||||||
val FRAGMENT_TAG = "retweet_quote"
|
val FRAGMENT_TAG = "retweet_quote"
|
||||||
private val SHOW_PROTECTED_CONFIRM = java.lang.Boolean.parseBoolean("false")
|
private val SHOW_PROTECTED_CONFIRM = java.lang.Boolean.parseBoolean("false")
|
||||||
|
|
||||||
fun show(fm: FragmentManager, status: ParcelableStatus): RetweetQuoteDialogFragment {
|
fun show(fm: FragmentManager, status: ParcelableStatus, accountKey: UserKey? = null): RetweetQuoteDialogFragment {
|
||||||
val args = Bundle()
|
|
||||||
args.putParcelable(EXTRA_STATUS, status)
|
|
||||||
val f = RetweetQuoteDialogFragment()
|
val f = RetweetQuoteDialogFragment()
|
||||||
f.arguments = args
|
f.arguments = Bundle {
|
||||||
|
this[EXTRA_STATUS] = status
|
||||||
|
this[EXTRA_ACCOUNT_KEY] = accountKey
|
||||||
|
}
|
||||||
f.show(fm, FRAGMENT_TAG)
|
f.show(fm, FRAGMENT_TAG)
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ import android.os.Bundle
|
||||||
import android.support.annotation.UiThread
|
import android.support.annotation.UiThread
|
||||||
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
||||||
import android.support.v4.app.hasRunningLoadersSafe
|
import android.support.v4.app.hasRunningLoadersSafe
|
||||||
import android.support.v4.content.AsyncTaskLoader
|
|
||||||
import android.support.v4.content.ContextCompat
|
import android.support.v4.content.ContextCompat
|
||||||
import android.support.v4.content.FixedAsyncTaskLoader
|
import android.support.v4.content.FixedAsyncTaskLoader
|
||||||
import android.support.v4.content.Loader
|
import android.support.v4.content.Loader
|
||||||
|
@ -98,8 +97,6 @@ import org.mariotaku.twidere.loader.ConversationLoader
|
||||||
import org.mariotaku.twidere.loader.ParcelableStatusLoader
|
import org.mariotaku.twidere.loader.ParcelableStatusLoader
|
||||||
import org.mariotaku.twidere.menu.FavoriteItemProvider
|
import org.mariotaku.twidere.menu.FavoriteItemProvider
|
||||||
import org.mariotaku.twidere.model.*
|
import org.mariotaku.twidere.model.*
|
||||||
import org.mariotaku.twidere.model.ParcelableStatusValuesCreator
|
|
||||||
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices
|
|
||||||
import org.mariotaku.twidere.model.analyzer.Share
|
import org.mariotaku.twidere.model.analyzer.Share
|
||||||
import org.mariotaku.twidere.model.analyzer.StatusView
|
import org.mariotaku.twidere.model.analyzer.StatusView
|
||||||
import org.mariotaku.twidere.model.message.FavoriteTaskEvent
|
import org.mariotaku.twidere.model.message.FavoriteTaskEvent
|
||||||
|
@ -259,6 +256,10 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
|
||||||
IntentUtils.openStatus(activity, accountKey, status.id)
|
IntentUtils.openStatus(activity, accountKey, status.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AbsStatusesFragment.REQUEST_FAVORITE_SELECT_ACCOUNT,
|
||||||
|
AbsStatusesFragment.REQUEST_RETWEET_SELECT_ACCOUNT -> {
|
||||||
|
AbsStatusesFragment.handleActionActivityResult(this, requestCode, resultCode, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,11 +311,17 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemActionClick(holder: ViewHolder, id: Int, position: Int) {
|
override fun onItemActionClick(holder: ViewHolder, id: Int, position: Int) {
|
||||||
val status = adapter.getStatus(position)
|
val status = adapter.getStatus(position) ?: return
|
||||||
AbsStatusesFragment.handleStatusActionClick(context, fragmentManager, twitterWrapper,
|
AbsStatusesFragment.handleActionClick(context, fragmentManager, twitterWrapper,
|
||||||
holder as StatusViewHolder, status, id)
|
holder as StatusViewHolder, status, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onItemActionLongClick(holder: RecyclerView.ViewHolder, id: Int, position: Int): Boolean {
|
||||||
|
val status = adapter.getStatus(position) ?: return false
|
||||||
|
return AbsStatusesFragment.handleActionLongClick(this, status, adapter.getItemId(position), id)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStatusClick(holder: IStatusViewHolder, position: Int) {
|
override fun onStatusClick(holder: IStatusViewHolder, position: Int) {
|
||||||
val status = adapter.getStatus(position) ?: return
|
val status = adapter.getStatus(position) ?: return
|
||||||
IntentUtils.openStatus(activity, status)
|
IntentUtils.openStatus(activity, status)
|
||||||
|
@ -339,15 +346,14 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
|
||||||
override fun onUserProfileClick(holder: IStatusViewHolder, position: Int) {
|
override fun onUserProfileClick(holder: IStatusViewHolder, position: Int) {
|
||||||
val status = adapter.getStatus(position)!!
|
val status = adapter.getStatus(position)!!
|
||||||
IntentUtils.openUserProfile(activity, status.account_key, status.user_key,
|
IntentUtils.openUserProfile(activity, status.account_key, status.user_key,
|
||||||
status.user_screen_name, preferences.getBoolean(KEY_NEW_DOCUMENT_API), Referral.TIMELINE_STATUS,
|
status.user_screen_name, preferences[newDocumentApiKey], Referral.TIMELINE_STATUS,
|
||||||
null)
|
null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaClick(view: View, media: ParcelableMedia, accountKey: UserKey?, id: Long) {
|
override fun onMediaClick(view: View, media: ParcelableMedia, accountKey: UserKey?, id: Long) {
|
||||||
val status = adapter.status
|
val status = adapter.status ?: return
|
||||||
if (status == null || media == null) return
|
IntentUtils.openMediaDirectly(activity, accountKey, status, media,
|
||||||
IntentUtils.openMediaDirectly(activity, accountKey, status, media, preferences.getBoolean(KEY_NEW_DOCUMENT_API),
|
preferences[newDocumentApiKey], null)
|
||||||
null)
|
|
||||||
// BEGIN HotMobi
|
// BEGIN HotMobi
|
||||||
val event = MediaEvent.create(activity, status, media, TimelineType.OTHER,
|
val event = MediaEvent.create(activity, status, media, TimelineType.OTHER,
|
||||||
adapter.mediaPreviewEnabled)
|
adapter.mediaPreviewEnabled)
|
||||||
|
|
|
@ -105,7 +105,7 @@ class ExtensionsListLoader(
|
||||||
val label: String
|
val label: String
|
||||||
val description: String
|
val description: String
|
||||||
val pname: String
|
val pname: String
|
||||||
val settings: String
|
val settings: String?
|
||||||
val icon: Drawable
|
val icon: Drawable
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package org.mariotaku.twidere.model.analyzer
|
package org.mariotaku.twidere.model.analyzer
|
||||||
|
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.extension.model.draftActionTypeString
|
import org.mariotaku.twidere.extension.model.draftActionTypeString
|
||||||
import org.mariotaku.twidere.extension.model.parcelableMediaTypeString
|
import org.mariotaku.twidere.extension.model.parcelableMediaTypeString
|
||||||
import org.mariotaku.twidere.model.Draft
|
import org.mariotaku.twidere.model.Draft
|
||||||
import org.mariotaku.twidere.model.ParcelableMedia
|
import org.mariotaku.twidere.model.ParcelableMedia
|
||||||
|
import org.mariotaku.twidere.task.twitter.UpdateStatusTask
|
||||||
import org.mariotaku.twidere.util.Analyzer
|
import org.mariotaku.twidere.util.Analyzer
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 2016/12/28.
|
* Created by mariotaku on 2016/12/28.
|
||||||
|
@ -17,7 +20,8 @@ data class UpdateStatus(
|
||||||
@ParcelableMedia.Type val mediaType: Int,
|
@ParcelableMedia.Type val mediaType: Int,
|
||||||
val hasLocation: Boolean,
|
val hasLocation: Boolean,
|
||||||
val preciseLocation: Boolean,
|
val preciseLocation: Boolean,
|
||||||
val success: Boolean
|
val success: Boolean,
|
||||||
|
val exception: Exception?
|
||||||
) : Analyzer.Event {
|
) : Analyzer.Event {
|
||||||
|
|
||||||
private val locationType: String get() = if (!hasLocation) {
|
private val locationType: String get() = if (!hasLocation) {
|
||||||
|
@ -28,6 +32,36 @@ data class UpdateStatus(
|
||||||
"place"
|
"place"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val errorReason: String? get() {
|
||||||
|
val ex = exception ?: return null
|
||||||
|
when (ex) {
|
||||||
|
is UpdateStatusTask.ShortenerNotFoundException,
|
||||||
|
is UpdateStatusTask.UploaderNotFoundException ->
|
||||||
|
return "extension not found"
|
||||||
|
else -> {
|
||||||
|
val cause = ex.cause
|
||||||
|
when (cause) {
|
||||||
|
is UpdateStatusTask.ExtensionVersionMismatchException ->
|
||||||
|
return "extension version mismatch"
|
||||||
|
is IOException ->
|
||||||
|
return "io exception"
|
||||||
|
is MicroBlogException -> {
|
||||||
|
if (cause.isCausedByNetworkIssue) {
|
||||||
|
return "network error"
|
||||||
|
}
|
||||||
|
return "request error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when (ex) {
|
||||||
|
is UpdateStatusTask.ShortenException,
|
||||||
|
is UpdateStatusTask.UploadException ->
|
||||||
|
return "extension error"
|
||||||
|
}
|
||||||
|
return "internal error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val name: String
|
override val name: String
|
||||||
get() = "Tweet"
|
get() = "Tweet"
|
||||||
|
|
||||||
|
@ -36,6 +70,7 @@ data class UpdateStatus(
|
||||||
action("Media Type", parcelableMediaTypeString(mediaType))
|
action("Media Type", parcelableMediaTypeString(mediaType))
|
||||||
action("Location Type", locationType)
|
action("Location Type", locationType)
|
||||||
action("Success", success.toString())
|
action("Success", success.toString())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,11 +378,11 @@ class LengthyOperationsService : BaseIntentService("lengthy_operations") {
|
||||||
Utils.setLastSeen(this, UserKey(recipientId, accountKey.host),
|
Utils.setLastSeen(this, UserKey(recipientId, accountKey.host),
|
||||||
System.currentTimeMillis())
|
System.currentTimeMillis())
|
||||||
|
|
||||||
return SingleResponse.getInstance(directMessage)
|
return SingleResponse(directMessage)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
return SingleResponse.getInstance<ParcelableDirectMessage>(e)
|
return SingleResponse(e)
|
||||||
} catch (e: MicroBlogException) {
|
} catch (e: MicroBlogException) {
|
||||||
return SingleResponse.getInstance<ParcelableDirectMessage>(e)
|
return SingleResponse(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ class UpdateStatusTask(
|
||||||
val hasLocation = statusUpdate.location != null
|
val hasLocation = statusUpdate.location != null
|
||||||
val preciseLocation = statusUpdate.display_coordinates
|
val preciseLocation = statusUpdate.display_coordinates
|
||||||
Analyzer.log(UpdateStatus(result.accountTypes.firstOrNull(), actionType, mediaType,
|
Analyzer.log(UpdateStatus(result.accountTypes.firstOrNull(), actionType, mediaType,
|
||||||
hasLocation, preciseLocation, result.succeed))
|
hasLocation, preciseLocation, result.succeed, result.exceptions.firstOrNull() ?: result.exception))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(UpdateStatusException::class)
|
@Throws(UpdateStatusException::class)
|
||||||
|
@ -110,11 +110,7 @@ class UpdateStatusTask(
|
||||||
uploadMedia(uploader, update, pendingUpdate)
|
uploadMedia(uploader, update, pendingUpdate)
|
||||||
shortenStatus(shortener, update, pendingUpdate)
|
shortenStatus(shortener, update, pendingUpdate)
|
||||||
|
|
||||||
try {
|
result = requestUpdateStatus(update, pendingUpdate, draftId)
|
||||||
result = requestUpdateStatus(update, pendingUpdate, draftId)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
return UpdateStatusResult(UpdateStatusException(e), draftId)
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaUploadCallback(uploader, pendingUpdate, result)
|
mediaUploadCallback(uploader, pendingUpdate, result)
|
||||||
statusShortenCallback(shortener, pendingUpdate, result)
|
statusShortenCallback(shortener, pendingUpdate, result)
|
||||||
|
@ -240,10 +236,12 @@ class UpdateStatusTask(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(UpdateStatusException::class)
|
||||||
private fun requestUpdateStatus(statusUpdate: ParcelableStatusUpdate,
|
private fun requestUpdateStatus(
|
||||||
pendingUpdate: PendingStatusUpdate,
|
statusUpdate: ParcelableStatusUpdate,
|
||||||
draftId: Long): UpdateStatusResult {
|
pendingUpdate: PendingStatusUpdate,
|
||||||
|
draftId: Long
|
||||||
|
): UpdateStatusResult {
|
||||||
|
|
||||||
stateCallback.onUpdatingStatus()
|
stateCallback.onUpdatingStatus()
|
||||||
|
|
||||||
|
@ -253,55 +251,54 @@ class UpdateStatusTask(
|
||||||
val account = statusUpdate.accounts[i]
|
val account = statusUpdate.accounts[i]
|
||||||
result.accountTypes[i] = account.type
|
result.accountTypes[i] = account.type
|
||||||
val microBlog = MicroBlogAPIFactory.getInstance(context, account.key)
|
val microBlog = MicroBlogAPIFactory.getInstance(context, account.key)
|
||||||
var mediaBody: MediaStreamBody? = null
|
|
||||||
try {
|
try {
|
||||||
when (account.type) {
|
val requestResult = when (account.type) {
|
||||||
AccountType.FANFOU -> {
|
AccountType.FANFOU -> {
|
||||||
// Call uploadPhoto if media present
|
// Call uploadPhoto if media present
|
||||||
if (!ArrayUtils.isEmpty(statusUpdate.media)) {
|
if (statusUpdate.media.isNotNullOrEmpty()) {
|
||||||
// Fanfou only allow one photo
|
// Fanfou only allow one photo
|
||||||
if (statusUpdate.media.size > 1) {
|
fanfouUpdateStatusWithPhoto(microBlog, statusUpdate, pendingUpdate,
|
||||||
result.exceptions[i] = MicroBlogException(
|
pendingUpdate.overrideTexts[i], account.size_limit, i)
|
||||||
context.getString(R.string.error_too_many_photos_fanfou))
|
|
||||||
} else {
|
|
||||||
val sizeLimit = account.size_limit
|
|
||||||
val firstMedia = statusUpdate.media.first()
|
|
||||||
mediaBody = getBodyFromMedia(context, mediaLoader, Uri.parse(firstMedia.uri),
|
|
||||||
sizeLimit, firstMedia.type, false, ContentLengthInputStream.ReadListener { length, position ->
|
|
||||||
stateCallback.onUploadingProgressChanged(-1, position, length)
|
|
||||||
})
|
|
||||||
val photoUpdate = PhotoStatusUpdate(mediaBody.body,
|
|
||||||
pendingUpdate.overrideTexts[i])
|
|
||||||
val requestResult = microBlog.uploadPhoto(photoUpdate)
|
|
||||||
|
|
||||||
result.statuses[i] = ParcelableStatusUtils.fromStatus(requestResult,
|
|
||||||
account.key, false)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
val requestResult = twitterUpdateStatus(microBlog, statusUpdate,
|
twitterUpdateStatus(microBlog, statusUpdate, pendingUpdate,
|
||||||
pendingUpdate, pendingUpdate.overrideTexts[i], i)
|
pendingUpdate.overrideTexts[i], i)
|
||||||
|
|
||||||
result.statuses[i] = ParcelableStatusUtils.fromStatus(requestResult,
|
|
||||||
account.key, false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val requestResult = twitterUpdateStatus(microBlog, statusUpdate,
|
twitterUpdateStatus(microBlog, statusUpdate, pendingUpdate,
|
||||||
pendingUpdate, pendingUpdate.overrideTexts[i], i)
|
pendingUpdate.overrideTexts[i], i)
|
||||||
|
|
||||||
result.statuses[i] = ParcelableStatusUtils.fromStatus(requestResult,
|
|
||||||
account.key, false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result.statuses[i] = ParcelableStatusUtils.fromStatus(requestResult,
|
||||||
|
account.key, false)
|
||||||
} catch (e: MicroBlogException) {
|
} catch (e: MicroBlogException) {
|
||||||
result.exceptions[i] = e
|
result.exceptions[i] = e
|
||||||
} finally {
|
|
||||||
Utils.closeSilently(mediaBody)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(MicroBlogException::class, UploadException::class)
|
||||||
|
private fun fanfouUpdateStatusWithPhoto(microBlog: MicroBlog, statusUpdate: ParcelableStatusUpdate,
|
||||||
|
pendingUpdate: PendingStatusUpdate, overrideText: String,
|
||||||
|
sizeLimit: SizeLimit, updateIndex: Int): Status {
|
||||||
|
if (statusUpdate.media.size > 1) {
|
||||||
|
throw MicroBlogException(context.getString(R.string.error_too_many_photos_fanfou))
|
||||||
|
}
|
||||||
|
val media = statusUpdate.media.first()
|
||||||
|
try {
|
||||||
|
return getBodyFromMedia(context, mediaLoader, Uri.parse(media.uri), sizeLimit, media.type,
|
||||||
|
false, ContentLengthInputStream.ReadListener { length, position ->
|
||||||
|
stateCallback.onUploadingProgressChanged(-1, position, length)
|
||||||
|
}).use { mediaBody ->
|
||||||
|
val photoUpdate = PhotoStatusUpdate(mediaBody.body, pendingUpdate.overrideTexts[updateIndex])
|
||||||
|
return@use microBlog.uploadPhoto(photoUpdate)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw UploadException(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calling Twitter's upload method. This method sets multiple owner for bandwidth saving
|
* Calling Twitter's upload method. This method sets multiple owner for bandwidth saving
|
||||||
*/
|
*/
|
||||||
|
@ -439,7 +436,7 @@ class UpdateStatusTask(
|
||||||
}
|
}
|
||||||
} catch (e: AbsServiceInterface.CheckServiceException) {
|
} catch (e: AbsServiceInterface.CheckServiceException) {
|
||||||
if (e is ExtensionVersionMismatchException) {
|
if (e is ExtensionVersionMismatchException) {
|
||||||
throw UploadException(context.getString(R.string.uploader_version_incompatible))
|
throw UploadException(context.getString(R.string.uploader_version_incompatible), e)
|
||||||
}
|
}
|
||||||
throw UploadException(e)
|
throw UploadException(e)
|
||||||
}
|
}
|
||||||
|
@ -622,25 +619,16 @@ class UpdateStatusTask(
|
||||||
|
|
||||||
|
|
||||||
open class UpdateStatusException : Exception {
|
open class UpdateStatusException : Exception {
|
||||||
constructor() : super()
|
protected constructor() : super()
|
||||||
|
|
||||||
constructor(detailMessage: String, throwable: Throwable) : super(detailMessage, throwable)
|
protected constructor(detailMessage: String, throwable: Throwable) : super(detailMessage, throwable)
|
||||||
|
|
||||||
constructor(throwable: Throwable) : super(throwable)
|
protected constructor(throwable: Throwable) : super(throwable)
|
||||||
|
|
||||||
constructor(message: String) : super(message)
|
protected constructor(message: String) : super(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
class UploaderNotFoundException : UpdateStatusException {
|
class UploaderNotFoundException(message: String) : UpdateStatusException(message)
|
||||||
|
|
||||||
constructor() : super()
|
|
||||||
|
|
||||||
constructor(detailMessage: String, throwable: Throwable) : super(detailMessage, throwable)
|
|
||||||
|
|
||||||
constructor(throwable: Throwable) : super(throwable)
|
|
||||||
|
|
||||||
constructor(message: String) : super(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
class UploadException : UpdateStatusException {
|
class UploadException : UpdateStatusException {
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.view.View.OnLongClickListener
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import kotlinx.android.synthetic.main.list_item_status.view.*
|
import kotlinx.android.synthetic.main.list_item_status.view.*
|
||||||
import org.mariotaku.ktextension.applyFontFamily
|
import org.mariotaku.ktextension.applyFontFamily
|
||||||
import org.mariotaku.twidere.Constants
|
|
||||||
import org.mariotaku.twidere.Constants.*
|
import org.mariotaku.twidere.Constants.*
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.TwidereConstants.USER_TYPE_FANFOU_COM
|
import org.mariotaku.twidere.TwidereConstants.USER_TYPE_FANFOU_COM
|
||||||
|
@ -40,7 +39,7 @@ import java.lang.ref.WeakReference
|
||||||
*
|
*
|
||||||
* Created by mariotaku on 14/11/19.
|
* Created by mariotaku on 14/11/19.
|
||||||
*/
|
*/
|
||||||
class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : ViewHolder(itemView), Constants, IStatusViewHolder {
|
class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : ViewHolder(itemView), IStatusViewHolder {
|
||||||
|
|
||||||
override val profileImageView: ProfileImageView by lazy { itemView.profileImage }
|
override val profileImageView: ProfileImageView by lazy { itemView.profileImage }
|
||||||
override val profileTypeView: ImageView by lazy { itemView.profileType }
|
override val profileTypeView: ImageView by lazy { itemView.profileType }
|
||||||
|
@ -463,6 +462,8 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
|
||||||
replyButton.setOnClickListener(eventListener)
|
replyButton.setOnClickListener(eventListener)
|
||||||
retweetButton.setOnClickListener(eventListener)
|
retweetButton.setOnClickListener(eventListener)
|
||||||
favoriteButton.setOnClickListener(eventListener)
|
favoriteButton.setOnClickListener(eventListener)
|
||||||
|
retweetButton.setOnLongClickListener(eventListener)
|
||||||
|
favoriteButton.setOnLongClickListener(eventListener)
|
||||||
|
|
||||||
mediaLabel.setOnClickListener(eventListener)
|
mediaLabel.setOnClickListener(eventListener)
|
||||||
|
|
||||||
|
@ -648,6 +649,12 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
|
||||||
}
|
}
|
||||||
return listener.onStatusLongClick(holder, position)
|
return listener.onStatusLongClick(holder, position)
|
||||||
}
|
}
|
||||||
|
holder.favoriteButton -> {
|
||||||
|
return listener.onItemActionLongClick(holder, R.id.favorite, position)
|
||||||
|
}
|
||||||
|
holder.retweetButton -> {
|
||||||
|
return listener.onItemActionLongClick(holder, R.id.retweet, position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue