added filter everywhere option

This commit is contained in:
Mariotaku Lee 2016-12-11 14:29:00 +08:00
parent c0e942e4f2
commit 0cc1ca39da
24 changed files with 578 additions and 229 deletions

View File

@ -15,4 +15,10 @@ class DataStoreUtilsTest {
val context = InstrumentationRegistry.getTargetContext()
DataStoreUtils.cleanDatabasesByItemLimit(context)
}
@Test
fun testGetAccountKeys() {
val context = InstrumentationRegistry.getTargetContext()
DataStoreUtils.getAccountKeys(context)
}
}

View File

@ -0,0 +1,18 @@
package org.mariotaku.twidere.util
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
/**
* Created by mariotaku on 2016/12/10.
*/
@RunWith(AndroidJUnit4::class)
class UtilsTest {
@Test
fun testHasAutoRefreshAccounts() {
val context = InstrumentationRegistry.getTargetContext()
Utils.hasAutoRefreshAccounts(context)
}
}

View File

@ -5,6 +5,8 @@ import com.bluelinelabs.logansquare.annotation.JsonObject;
import org.mariotaku.library.objectcursor.annotation.CursorField;
import org.mariotaku.library.objectcursor.annotation.CursorObject;
import org.mariotaku.twidere.model.util.UserKeyConverter;
import org.mariotaku.twidere.model.util.UserKeyCursorFieldConverter;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import java.util.List;
@ -69,9 +71,9 @@ public class FiltersData {
@JsonObject
@CursorObject(valuesCreator = true)
public static class UserItem {
@CursorField(Filters.Users.USER_KEY)
@JsonField(name = "user_key")
String userKey;
@CursorField(value = Filters.Users.USER_KEY, converter = UserKeyCursorFieldConverter.class)
@JsonField(name = "user_key", typeConverter = UserKeyConverter.class)
UserKey userKey;
@CursorField(Filters.Users.NAME)
@JsonField(name = "name")
String name;
@ -79,7 +81,7 @@ public class FiltersData {
@JsonField(name = "screen_name")
String screenName;
public String getUserKey() {
public UserKey getUserKey() {
return userKey;
}
@ -91,6 +93,18 @@ public class FiltersData {
return screenName;
}
public void setName(String name) {
this.name = name;
}
public void setScreenName(String screenName) {
this.screenName = screenName;
}
public void setUserKey(UserKey userKey) {
this.userKey = userKey;
}
@Override
public String toString() {
return "UserItem{" +
@ -112,6 +126,10 @@ public class FiltersData {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "BaseItem{" +

View File

@ -81,7 +81,7 @@ public class FriendshipTaskEvent {
}
@IntDef({Action.ACCEPT, Action.DENY, Action.FOLLOW, Action.UNFOLLOW, Action.BLOCK,
Action.UNBLOCK, Action.MUTE, Action.UNMUTE})
Action.UNBLOCK, Action.MUTE, Action.UNMUTE, Action.FILTER, Action.UNFILTER})
public @interface Action {
int ACCEPT = 1;
int DENY = 2;
@ -91,5 +91,7 @@ public class FriendshipTaskEvent {
int UNBLOCK = 6;
int MUTE = 7;
int UNMUTE = 8;
int FILTER = 9;
int UNFILTER = 10;
}
}

View File

@ -74,7 +74,6 @@ import org.mariotaku.twidere.model.message.FavoriteTaskEvent;
import org.mariotaku.twidere.model.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.model.message.GetMessagesTaskEvent;
import org.mariotaku.twidere.model.message.GetStatusesTaskEvent;
import org.mariotaku.twidere.model.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.model.message.SavedSearchDestroyedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.message.StatusRetweetedEvent;
@ -87,7 +86,6 @@ import org.mariotaku.twidere.model.message.UsersBlockedEvent;
import org.mariotaku.twidere.model.util.AccountUtils;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.model.util.ParcelableUserListUtils;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
@ -116,15 +114,11 @@ import org.mariotaku.twidere.task.ManagedAsyncTask;
import org.mariotaku.twidere.task.ReportSpamAndBlockTask;
import org.mariotaku.twidere.task.twitter.GetActivitiesTask;
import org.mariotaku.twidere.util.collection.CompactHashSet;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import edu.tsinghua.hotmobi.HotMobiLogger;
import edu.tsinghua.hotmobi.model.TimelineType;
import edu.tsinghua.hotmobi.model.TweetEvent;
@ -217,8 +211,8 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
AsyncTaskUtils.executeTask(task);
}
public void createBlockAsync(final UserKey accountKey, final UserKey userKey) {
final CreateUserBlockTask task = new CreateUserBlockTask(context);
public void createBlockAsync(final UserKey accountKey, final UserKey userKey, boolean filterEverywhere) {
final CreateUserBlockTask task = new CreateUserBlockTask(context, filterEverywhere);
task.setup(accountKey, userKey);
TaskStarter.execute(task);
}

View File

@ -55,6 +55,9 @@ import org.mariotaku.sqliteqb.library.query.SQLSelectQuery;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.extension.AccountExtensionsKt;
import org.mariotaku.twidere.model.FiltersData;
import org.mariotaku.twidere.model.FiltersData$BaseItemValuesCreator;
import org.mariotaku.twidere.model.FiltersData$UserItemValuesCreator;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices;
import org.mariotaku.twidere.model.ParcelableActivityValuesCreator;
@ -675,13 +678,15 @@ public class DataStoreUtils implements Constants {
@NonNull
public static UserKey[] getAccountKeys(final Context context) {
AccountManager am = AccountManager.get(context);
final AccountManager am = AccountManager.get(context);
final Account[] accounts = AccountUtils.getAccounts(am);
final UserKey[] keys = new UserKey[accounts.length];
for (int i = 0; i < accounts.length; i++) {
keys[i] = AccountExtensionsKt.getAccountKey(accounts[i], am);
final List<UserKey> keys = new ArrayList<>(accounts.length);
for (Account account : accounts) {
String keyString = am.getUserData(account, ACCOUNT_USER_DATA_KEY);
if (keyString == null) continue;
keys.add(UserKey.valueOf(keyString));
}
return keys;
return keys.toArray(new UserKey[keys.size()]);
}
@Nullable
@ -1063,6 +1068,37 @@ public class DataStoreUtils implements Constants {
since, sinceColumn, followingOnly, accountIds);
}
public static void addToFilter(Context context, ParcelableUser user, boolean filterAnywhere) {
final ContentResolver cr = context.getContentResolver();
final FiltersData.UserItem userItem = new FiltersData.UserItem();
userItem.setUserKey(user.key);
userItem.setScreenName(user.screen_name);
userItem.setName(user.name);
try {
// Insert to filtered users
cr.insert(Filters.Users.CONTENT_URI, FiltersData$UserItemValuesCreator.create(userItem));
if (filterAnywhere) {
// Insert user mention to keywords
final FiltersData.BaseItem keywordItem = new FiltersData.BaseItem();
keywordItem.setValue("@" + userItem.getScreenName());
cr.insert(Filters.Keywords.CONTENT_URI, FiltersData$BaseItemValuesCreator.create(keywordItem));
// Insert user link (without scheme) to links
final FiltersData.BaseItem linkItem = new FiltersData.BaseItem();
Uri userLink = LinkCreator.getUserWebLink(user);
String linkWithoutScheme = userLink.toString();
int idx;
if ((idx = linkWithoutScheme.indexOf("://")) >= 0) {
linkWithoutScheme = linkWithoutScheme.substring(idx + 3);
}
linkItem.setValue(linkWithoutScheme);
cr.insert(Filters.Links.CONTENT_URI, FiltersData$BaseItemValuesCreator.create(linkItem));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public interface UpdateActivityAction {
void process(ParcelableActivity activity);

View File

@ -106,7 +106,7 @@ public class SQLiteDatabaseWrapper {
return mDatabase.update(table, values, whereClause, whereArgs);
}
private void tryCreateDatabase() {
private synchronized void tryCreateDatabase() {
if (mLazyLoadCallback == null || mDatabase != null) return;
mDatabase = mLazyLoadCallback.onCreateSQLiteDatabase();
if (mDatabase == null)

View File

@ -1191,6 +1191,7 @@ public final class Utils implements Constants {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
DataStoreUtils.prepareDatabase(context);
if (isNetworkAvailable(appContext) && hasAutoRefreshAccounts(appContext)) {
if (BuildConfig.DEBUG) {
Log.d(LOGTAG, "Start background refresh service");

View File

@ -0,0 +1,91 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.fragment
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.widget.CheckBox
import android.widget.TextView
import android.widget.Toast
import org.mariotaku.twidere.R
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_USER
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_NAME_FIRST
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.message.FriendshipTaskEvent
import org.mariotaku.twidere.util.DataStoreUtils
class AddUserFilterDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
private val user: ParcelableUser by lazy { arguments.getParcelable<ParcelableUser>(EXTRA_USER) }
override fun onClick(dialog: DialogInterface, which: Int) {
when (which) {
DialogInterface.BUTTON_POSITIVE -> {
val filterEverywhere = ((dialog as Dialog).findViewById(R.id.filterEverywhereToggle) as CheckBox).isChecked
DataStoreUtils.addToFilter(context, user, filterEverywhere)
bus.post(FriendshipTaskEvent(FriendshipTaskEvent.Action.FILTER, user.account_key, user.key).apply {
isFinished = true
isSucceeded = true
})
Toast.makeText(context, R.string.message_toast_added_to_filter, Toast.LENGTH_SHORT).show()
}
else -> {
}
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(context)
val nameFirst = preferences.getBoolean(KEY_NAME_FIRST)
val displayName = userColorNameManager.getDisplayName(user, nameFirst)
builder.setTitle(R.string.add_to_filter)
builder.setView(R.layout.dialog_filter_user_confirm)
builder.setPositiveButton(android.R.string.ok, this)
builder.setNegativeButton(android.R.string.cancel, null)
val dialog = builder.create()
dialog.setOnShowListener {
val confirmMessageView = dialog.findViewById(R.id.confirmMessage) as TextView
val filterEverywhereHelp = dialog.findViewById(R.id.filterEverywhereHelp)!!
filterEverywhereHelp.setOnClickListener {
MessageDialogFragment.show(childFragmentManager, title = getString(R.string.filter_everywhere),
message = getString(R.string.filter_everywhere_description), tag = "filter_everywhere_help")
}
confirmMessageView.text = getString(R.string.filter_user_confirm_message, displayName)
}
return dialog
}
companion object {
val FRAGMENT_TAG = "add_user_filter"
fun show(fm: FragmentManager, user: ParcelableUser): AddUserFilterDialogFragment {
val args = Bundle()
args.putParcelable(EXTRA_USER, user)
val f = AddUserFilterDialogFragment()
f.arguments = args
f.show(fm, FRAGMENT_TAG)
return f
}
}
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment
import android.content.Context
import android.support.v4.app.DialogFragment
import com.squareup.otto.Bus
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
@ -38,6 +39,8 @@ open class BaseDialogFragment : DialogFragment(), Constants {
lateinit var validator: TwidereValidator
@Inject
lateinit var keyboardShortcutsHandler: KeyboardShortcutsHandler
@Inject
lateinit var bus: Bus
override fun onAttach(context: Context?) {
super.onAttach(context)

View File

@ -54,6 +54,7 @@ import org.mariotaku.twidere.adapter.ComposeAutoCompleteAdapter
import org.mariotaku.twidere.adapter.SourceAutoCompleteAdapter
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.`FiltersData$UserItemCursorIndices`
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.Utils.getDefaultAccountKey
@ -276,16 +277,6 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
}
private class FilterListAdapter(context: Context) : SimpleCursorAdapter(context, android.R.layout.simple_list_item_activated_1, null, BaseFiltersFragment.FilterListAdapter.from, BaseFiltersFragment.FilterListAdapter.to, 0) {
companion object {
private val from = arrayOf(Filters.VALUE)
private val to = intArrayOf(android.R.id.text1)
}
}
class FilteredKeywordsFragment : BaseFiltersFragment() {
override val contentUri: Uri
@ -294,9 +285,9 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
public override val contentColumns: Array<String>
get() = Filters.Keywords.COLUMNS
}
class FilteredLinksFragment : BaseFiltersFragment() {
public override val contentColumns: Array<String>
@ -332,6 +323,19 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
}
private class FilterListAdapter(
context: Context
) : SimpleCursorAdapter(context, R.layout.simple_list_item_activated_1, null,
BaseFiltersFragment.FilterListAdapter.from, BaseFiltersFragment.FilterListAdapter.to, 0) {
companion object {
private val from = arrayOf(Filters.VALUE)
private val to = intArrayOf(android.R.id.text1)
}
}
class FilteredUsersFragment : BaseFiltersFragment() {
@ -374,16 +378,19 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
return FilterUsersListAdapter(context)
}
class FilterUsersListAdapter internal constructor(context: Context) : SimpleCursorAdapter(context, android.R.layout.simple_list_item_activated_2, null, arrayOfNulls<String>(0), IntArray(0), 0) {
class FilterUsersListAdapter(
context: Context
) : SimpleCursorAdapter(context, R.layout.simple_list_item_activated_2, null,
emptyArray(), IntArray(0), 0) {
private val nameFirst: Boolean
@Inject
lateinit var userColorNameManager: UserColorNameManager
@Inject
lateinit var preferences: SharedPreferencesWrapper
private var userIdIdx: Int = 0
private var nameIdx: Int = 0
private var screenNameIdx: Int = 0
private val nameFirst: Boolean
private var indices: `FiltersData$UserItemCursorIndices`? = null
init {
GeneralComponentHelper.build(context).inject(this)
@ -392,11 +399,12 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
override fun bindView(view: View, context: Context?, cursor: Cursor) {
super.bindView(view, context, cursor)
val indices = this.indices!!
val text1 = view.findViewById(android.R.id.text1) as TextView
val text2 = view.findViewById(android.R.id.text2) as TextView
val userId = UserKey.valueOf(cursor.getString(userIdIdx))
val name = cursor.getString(nameIdx)
val screenName = cursor.getString(screenNameIdx)
val userId = UserKey.valueOf(cursor.getString(indices.userKey))
val name = cursor.getString(indices.name)
val screenName = cursor.getString(indices.screenName)
val displayName = userColorNameManager.getDisplayName(userId, name, screenName,
nameFirst)
text1.text = displayName
@ -406,9 +414,7 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
override fun swapCursor(c: Cursor?): Cursor? {
val old = super.swapCursor(c)
if (c != null) {
userIdIdx = c.getColumnIndex(Filters.Users.USER_KEY)
nameIdx = c.getColumnIndex(Filters.Users.NAME)
screenNameIdx = c.getColumnIndex(Filters.Users.SCREEN_NAME)
indices = `FiltersData$UserItemCursorIndices`(c)
}
return old
}

View File

@ -24,6 +24,8 @@ import android.content.DialogInterface
import android.os.Bundle
import android.support.v4.app.FragmentManager
import android.support.v7.app.AlertDialog
import android.widget.CheckBox
import android.widget.TextView
import org.mariotaku.twidere.R
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_USER
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_NAME_FIRST
@ -31,13 +33,13 @@ import org.mariotaku.twidere.model.ParcelableUser
class CreateUserBlockDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
private val user: ParcelableUser by lazy { arguments.getParcelable<ParcelableUser>(EXTRA_USER) }
override fun onClick(dialog: DialogInterface, which: Int) {
when (which) {
DialogInterface.BUTTON_POSITIVE -> {
val user = user
val twitter = twitterWrapper
if (user == null) return
twitter.createBlockAsync(user.account_key, user.key)
val filterEverywhere = ((dialog as Dialog).findViewById(R.id.filterEverywhereToggle) as CheckBox).isChecked
twitterWrapper.createBlockAsync(user.account_key, user.key, filterEverywhere)
}
else -> {
}
@ -45,27 +47,25 @@ class CreateUserBlockDialogFragment : BaseDialogFragment(), DialogInterface.OnCl
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val activity = activity
val context = activity
val builder = AlertDialog.Builder(context)
val user = user
if (user != null) {
val nameFirst = preferences.getBoolean(KEY_NAME_FIRST)
val displayName = userColorNameManager.getDisplayName(user, nameFirst)
builder.setTitle(getString(R.string.block_user, displayName))
builder.setMessage(getString(R.string.block_user_confirm_message, displayName))
}
val nameFirst = preferences.getBoolean(KEY_NAME_FIRST)
val displayName = userColorNameManager.getDisplayName(user, nameFirst)
builder.setTitle(getString(R.string.block_user, displayName))
builder.setView(R.layout.dialog_block_user_confirm)
builder.setPositiveButton(android.R.string.ok, this)
builder.setNegativeButton(android.R.string.cancel, null)
return builder.create()
}
private val user: ParcelableUser?
get() {
val args = arguments
if (!args.containsKey(EXTRA_USER)) return null
return args.getParcelable<ParcelableUser>(EXTRA_USER)
val dialog = builder.create()
dialog.setOnShowListener {
val confirmMessageView = dialog.findViewById(R.id.confirmMessage) as TextView
val filterEverywhereHelp = dialog.findViewById(R.id.filterEverywhereHelp)!!
filterEverywhereHelp.setOnClickListener {
MessageDialogFragment.show(childFragmentManager, title = getString(R.string.filter_everywhere),
message = getString(R.string.filter_everywhere_description), tag = "filter_everywhere_help")
}
confirmMessageView.text = getString(R.string.block_user_confirm_message, displayName)
}
return dialog
}
companion object {

View File

@ -22,7 +22,11 @@ package org.mariotaku.twidere.fragment
import android.app.AlertDialog
import android.app.Dialog
import android.os.Bundle
import android.support.v4.app.FragmentActivity
import android.support.v4.app.FragmentManager
import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.set
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_MESSAGE
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_TITLE
/**
* Created by mariotaku on 14-6-24.
@ -33,28 +37,26 @@ class MessageDialogFragment : BaseDialogFragment() {
val activity = activity
val builder = AlertDialog.Builder(activity)
val args = arguments
builder.setTitle(args.getString(EXTRA_TITLE))
builder.setMessage(args.getString(EXTRA_MESSAGE))
builder.setPositiveButton(android.R.string.ok, null)
return builder.create()
}
companion object {
private val EXTRA_MESSAGE = "message"
fun show(activity: FragmentActivity, message: String, tag: String): MessageDialogFragment {
val df = MessageDialogFragment()
val args = Bundle()
args.putString(EXTRA_MESSAGE, message)
df.arguments = args
df.show(activity.supportFragmentManager, tag)
fun show(fm: FragmentManager, title: String? = null, message: String, tag: String): MessageDialogFragment {
val df = create(title, message)
df.show(fm, tag)
return df
}
fun create(message: String): MessageDialogFragment {
fun create(title: String? = null, message: String): MessageDialogFragment {
val df = MessageDialogFragment()
val args = Bundle()
args.putString(EXTRA_MESSAGE, message)
df.arguments = args
df.arguments = Bundle {
this[EXTRA_TITLE] = title
this[EXTRA_MESSAGE] = message
}
return df
}
}

View File

@ -191,9 +191,9 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
override fun onClick(widget: View) {
val activity = activity
if (activity == null || activity.isFinishing) return
MessageDialogFragment.show(activity,
getString(R.string.cant_load_all_replies_explanation),
"cant_load_all_replies_explanation")
MessageDialogFragment.show(activity.supportFragmentManager,
message = getString(R.string.cant_load_all_replies_explanation),
tag = "cant_load_all_replies_explanation")
}
}, spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
}

View File

@ -140,8 +140,8 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
override val toolbar: Toolbar
get() = profileContentContainer.toolbar
private var mActionBarBackground: ActionBarDrawable? = null
private var pagerAdapter: SupportTabsAdapter? = null
private var actionBarBackground: ActionBarDrawable? = null
private lateinit var pagerAdapter: SupportTabsAdapter
// Data fields
var user: ParcelableUser? = null
@ -149,18 +149,18 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
private var account: AccountDetails? = null
private var relationship: ParcelableRelationship? = null
private var locale: Locale? = null
private var mGetUserInfoLoaderInitialized: Boolean = false
private var mGetFriendShipLoaderInitialized: Boolean = false
private var mBannerWidth: Int = 0
private var getUserInfoLoaderInitialized: Boolean = false
private var getFriendShipLoaderInitialized: Boolean = false
private var bannerWidth: Int = 0
private var cardBackgroundColor: Int = 0
private var actionBarShadowColor: Int = 0
private var uiColor: Int = 0
private var mPrimaryColor: Int = 0
private var mPrimaryColorDark: Int = 0
private var primaryColor: Int = 0
private var primaryColorDark: Int = 0
private var nameFirst: Boolean = false
private var mPreviousTabItemIsDark: Int = 0
private var mPreviousActionBarItemIsDark: Int = 0
private var mHideBirthdayView: Boolean = false
private var previousTabItemIsDark: Int = 0
private var previousActionBarItemIsDark: Int = 0
private var hideBirthdayView: Boolean = false
private var userEvent: UserEvent? = null
private val friendshipLoaderCallbacks = object : LoaderCallbacks<SingleResponse<ParcelableRelationship>> {
@ -172,11 +172,11 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
if (user != null && user.key == accountKey) {
followingYouIndicator.visibility = View.GONE
followContainer.follow.visibility = View.VISIBLE
followProgress!!.visibility = View.VISIBLE
followProgress.visibility = View.VISIBLE
} else {
followingYouIndicator.visibility = View.GONE
followContainer.follow.visibility = View.GONE
followProgress!!.visibility = View.VISIBLE
followProgress.visibility = View.VISIBLE
}
return UserRelationshipLoader(activity, accountKey, user)
}
@ -187,7 +187,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
override fun onLoadFinished(loader: Loader<SingleResponse<ParcelableRelationship>>,
data: SingleResponse<ParcelableRelationship>) {
followProgress!!.visibility = View.GONE
followProgress.visibility = View.GONE
val relationship = data.data
displayRelationship(user, relationship)
updateOptionsMenuVisibility()
@ -285,18 +285,18 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
activity.invalidateOptionsMenu()
followContainer.follow.isEnabled = userRelationship.blocking || !userRelationship.blocked_by
if (userRelationship.blocked_by) {
pagesErrorContainer!!.visibility = View.GONE
pagesErrorText!!.text = null
pagesContent!!.visibility = View.VISIBLE
pagesErrorContainer.visibility = View.GONE
pagesErrorText.text = null
pagesContent.visibility = View.VISIBLE
} else if (!userRelationship.following && user.is_protected) {
pagesErrorContainer!!.visibility = View.VISIBLE
pagesErrorText!!.setText(R.string.user_protected_summary)
pagesErrorIcon!!.setImageResource(R.drawable.ic_info_locked)
pagesContent!!.visibility = View.GONE
pagesErrorContainer.visibility = View.VISIBLE
pagesErrorText.setText(R.string.user_protected_summary)
pagesErrorIcon.setImageResource(R.drawable.ic_info_locked)
pagesContent.visibility = View.GONE
} else {
pagesErrorContainer!!.visibility = View.GONE
pagesErrorText!!.text = null
pagesContent!!.visibility = View.VISIBLE
pagesErrorContainer.visibility = View.GONE
pagesErrorText.text = null
pagesContent.visibility = View.VISIBLE
}
if (userRelationship.blocking) {
followContainer.follow.setText(R.string.unblock)
@ -340,7 +340,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
override fun isScrollContent(x: Float, y: Float): Boolean {
val v = viewPager
val location = IntArray(2)
v!!.getLocationInWindow(location)
v.getLocationInWindow(location)
return x >= location[0] && x <= location[0] + v.width
&& y >= location[1] && y <= location[1] + v.height
}
@ -361,7 +361,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
actionBar.subtitle = null
return
}
val spec = pagerAdapter!!.getTab(viewPager.currentItem)
val spec = pagerAdapter.getTab(viewPager.currentItem)
assert(spec.type != null)
when (spec.type) {
TAB_TYPE_STATUSES -> {
@ -429,13 +429,13 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
this.account = account
if (user == null || user.key == null) {
profileImage.visibility = View.GONE
profileType!!.visibility = View.GONE
profileType.visibility = View.GONE
if (activity is ATEActivity) {
setUiColor(Config.primaryColor(activity, activity.ateKey))
}
return
}
val adapter = pagerAdapter!!
val adapter = pagerAdapter
for (i in 0 until adapter.count) {
val sf = adapter.instantiateItem(viewPager, i) as? AbsStatusesFragment
sf?.initLoaderIfNeeded()
@ -445,8 +445,8 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
val lm = loaderManager
lm.destroyLoader(LOADER_ID_USER)
lm.destroyLoader(LOADER_ID_FRIENDSHIP)
cardContent!!.visibility = View.VISIBLE
errorContainer!!.visibility = View.GONE
cardContent.visibility = View.VISIBLE
errorContainer.visibility = View.GONE
progressContainer.visibility = View.GONE
this.user = user
profileImage.setBorderColor(if (user.color != 0) user.color else Color.WHITE)
@ -485,8 +485,8 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
listedContainer.listedCount.text = Utils.getLocalizedNumber(locale, user.listed_count)
val groupsCount = if (user.extras != null) user.extras.groups_count else -1
groupsContainer.groupsCount.text = Utils.getLocalizedNumber(locale, groupsCount)
followersContainer.followersCount!!.text = Utils.getLocalizedNumber(locale, user.followers_count)
friendsContainer.friendsCount!!.text = Utils.getLocalizedNumber(locale, user.friends_count)
followersContainer.followersCount.text = Utils.getLocalizedNumber(locale, user.followers_count)
friendsContainer.friendsCount.text = Utils.getLocalizedNumber(locale, user.friends_count)
listedContainer.visibility = if (user.listed_count < 0) View.GONE else View.VISIBLE
groupsContainer.visibility = if (groupsCount < 0) View.GONE else View.VISIBLE
@ -500,7 +500,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
setUiColor(Config.primaryColor(activity, activity.ateKey))
}
val defWidth = resources.displayMetrics.widthPixels
val width = if (mBannerWidth > 0) mBannerWidth else defWidth
val width = if (bannerWidth > 0) bannerWidth else defWidth
val bannerUrl = ParcelableUserUtils.getProfileBannerUrl(user)
if (ObjectUtils.notEqual(profileBanner.tag, bannerUrl) || profileBanner.drawable == null) {
profileBanner.tag = bannerUrl
@ -517,7 +517,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
val currentMonth = cal.get(Calendar.MONTH)
val currentDay = cal.get(Calendar.DAY_OF_MONTH)
cal.timeInMillis = user.created_at
if (cal.get(Calendar.MONTH) == currentMonth && cal.get(Calendar.DAY_OF_MONTH) == currentDay && !mHideBirthdayView) {
if (cal.get(Calendar.MONTH) == currentMonth && cal.get(Calendar.DAY_OF_MONTH) == currentDay && !hideBirthdayView) {
profileBirthdayBanner.visibility = View.VISIBLE
} else {
profileBirthdayBanner.visibility = View.GONE
@ -530,8 +530,8 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
override val currentVisibleFragment: Fragment?
get() {
val currentItem = viewPager.currentItem
if (currentItem < 0 || currentItem >= pagerAdapter!!.count) return null
return pagerAdapter!!.instantiateItem(viewPager, currentItem) as Fragment
if (currentItem < 0 || currentItem >= pagerAdapter.count) return null
return pagerAdapter.instantiateItem(viewPager, currentItem) as Fragment
}
override fun triggerRefresh(position: Int): Boolean {
@ -552,15 +552,15 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
args.putParcelable(EXTRA_USER_KEY, userKey)
args.putString(EXTRA_SCREEN_NAME, screenName)
args.putBoolean(EXTRA_OMIT_INTENT_EXTRA, omitIntentExtra)
if (!mGetUserInfoLoaderInitialized) {
if (!getUserInfoLoaderInitialized) {
lm.initLoader(LOADER_ID_USER, args, userInfoLoaderCallbacks)
mGetUserInfoLoaderInitialized = true
getUserInfoLoaderInitialized = true
} else {
lm.restartLoader(LOADER_ID_USER, args, userInfoLoaderCallbacks)
}
if (userKey == null && screenName == null) {
cardContent!!.visibility = View.GONE
errorContainer!!.visibility = View.GONE
cardContent.visibility = View.GONE
errorContainer.visibility = View.GONE
}
}
@ -628,8 +628,8 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater!!.inflate(R.layout.fragment_user, container, false)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_user, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
@ -738,8 +738,8 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
setUiColor(uiColor)
}
override fun onSaveInstanceState(outState: Bundle?) {
outState!!.putParcelable(EXTRA_USER, user)
override fun onSaveInstanceState(outState: Bundle) {
outState.putParcelable(EXTRA_USER, user)
super.onSaveInstanceState(outState)
}
@ -752,17 +752,17 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
super.onDestroyView()
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
inflater!!.inflate(R.menu.menu_user_profile, menu)
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_user_profile, menu)
}
@UiThread
override fun onPrepareOptionsMenu(menu: Menu?) {
override fun onPrepareOptionsMenu(menu: Menu) {
val user = user ?: return
val account = this.account
val isMyself = user.account_key.maybeEquals(user.key)
val mentionItem = menu!!.findItem(R.id.mention)
val mentionItem = menu.findItem(R.id.mention)
if (mentionItem != null) {
val displayName = UserColorNameManager.decideDisplayName(user.nickname,
user.name, user.screen_name, nameFirst)
@ -828,19 +828,19 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
val drawer = userProfileDrawer
if (drawer != null) {
val offset = drawer.paddingTop - drawer.headerTop
mPreviousActionBarItemIsDark = 0
mPreviousTabItemIsDark = 0
previousActionBarItemIsDark = 0
previousTabItemIsDark = 0
updateScrollOffset(offset)
}
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val context = context
val twitter = twitterWrapper
val user = user
val userRelationship = relationship
if (user == null) return false
when (item!!.itemId) {
when (item.itemId) {
R.id.block -> {
if (userRelationship == null) return true
if (userRelationship.blocking) {
@ -860,11 +860,10 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
val whereArgs = arrayOf(user.key.toString())
cr.delete(Filters.Users.CONTENT_URI, where, whereArgs)
Utils.showInfoMessage(activity, R.string.message_user_unmuted, false)
getFriendship()
} else {
cr.insert(Filters.Users.CONTENT_URI, ContentValuesCreator.createFilteredUser(user))
Utils.showInfoMessage(activity, R.string.message_user_muted, false)
AddUserFilterDialogFragment.show(fragmentManager, user)
}
getFriendship()
}
R.id.mute_user -> {
if (userRelationship == null) return true
@ -1033,14 +1032,14 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
when (action) {
ACTION_NAVIGATION_PREVIOUS_TAB -> {
val previous = viewPager.currentItem - 1
if (previous >= 0 && previous < pagerAdapter!!.count) {
if (previous >= 0 && previous < pagerAdapter.count) {
viewPager.setCurrentItem(previous, true)
}
return true
}
ACTION_NAVIGATION_NEXT_TAB -> {
val next = viewPager.currentItem + 1
if (next >= 0 && next < pagerAdapter!!.count) {
if (next >= 0 && next < pagerAdapter.count) {
viewPager.setCurrentItem(next, true)
}
return true
@ -1172,7 +1171,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
IntentUtils.openProfileEditor(getActivity(), user.account_key)
}
R.id.profileBirthdayBanner -> {
mHideBirthdayView = true
hideBirthdayView = true
profileBirthdayBanner.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out))
profileBirthdayBanner.visibility = View.GONE
}
@ -1227,7 +1226,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
}
override fun onSizeChanged(view: View, w: Int, h: Int, oldw: Int, oldh: Int) {
mBannerWidth = w
bannerWidth = w
if (w != oldw || h != oldh) {
requestFitSystemWindows()
}
@ -1260,9 +1259,9 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
val args = Bundle()
args.putParcelable(EXTRA_ACCOUNT_KEY, user.account_key)
args.putParcelable(EXTRA_USER, user)
if (!mGetFriendShipLoaderInitialized) {
if (!getFriendShipLoaderInitialized) {
lm.initLoader(LOADER_ID_FRIENDSHIP, args, friendshipLoaderCallbacks)
mGetFriendShipLoaderInitialized = true
getFriendShipLoaderInitialized = true
} else {
lm.restartLoader(LOADER_ID_FRIENDSHIP, args, friendshipLoaderCallbacks)
}
@ -1275,21 +1274,21 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
private fun setUiColor(color: Int) {
uiColor = color
mPreviousActionBarItemIsDark = 0
mPreviousTabItemIsDark = 0
if (mActionBarBackground == null) {
previousActionBarItemIsDark = 0
previousTabItemIsDark = 0
if (actionBarBackground == null) {
setupBaseActionBar()
}
val activity = activity as BaseActivity
if (Config.coloredActionBar(activity, activity.ateKey)) {
mPrimaryColor = color
mPrimaryColorDark = ThemeUtils.computeDarkColor(color)
primaryColor = color
primaryColorDark = ThemeUtils.computeDarkColor(color)
} else {
mPrimaryColor = Config.primaryColor(activity, activity.ateKey)
mPrimaryColorDark = Color.BLACK
primaryColor = Config.primaryColor(activity, activity.ateKey)
primaryColorDark = Color.BLACK
}
if (mActionBarBackground != null) {
mActionBarBackground!!.color = mPrimaryColor
if (actionBarBackground != null) {
actionBarBackground!!.color = primaryColor
}
val taskColor: Int
if (Config.coloredActionBar(activity, activity.ateKey)) {
@ -1310,7 +1309,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
urlContainer.url.setLinkTextColor(optimalAccentColor)
profileBanner.setBackgroundColor(color)
toolbarTabs.setBackgroundColor(mPrimaryColor)
toolbarTabs.setBackgroundColor(primaryColor)
val drawer = userProfileDrawer
if (drawer != null) {
@ -1322,13 +1321,13 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
private fun setupBaseActionBar() {
val activity = activity as? LinkHandlerActivity ?: return
val actionBar = activity.supportActionBar ?: return
val shadow = ResourcesCompat.getDrawable(activity.resources, R.drawable.shadow_user_banner_action_bar, null)
mActionBarBackground = ActionBarDrawable(shadow!!)
val shadow = ResourcesCompat.getDrawable(activity.resources, R.drawable.shadow_user_banner_action_bar, null)!!
actionBarBackground = ActionBarDrawable(shadow)
if (!ThemeUtils.isWindowFloating(activity) && ThemeUtils.isTransparentBackground(activity.currentThemeBackgroundOption)) {
// mActionBarBackground.setAlpha(ThemeUtils.getActionBarAlpha(linkHandler.getCurrentThemeBackgroundAlpha()));
profileBanner.alpha = activity.currentThemeBackgroundAlpha / 255f
}
actionBar.setBackgroundDrawable(mActionBarBackground)
actionBar.setBackgroundDrawable(actionBarBackground)
}
private fun setupUserPages() {
@ -1344,39 +1343,35 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
tabArgs.putParcelable(EXTRA_USER_KEY, args.getParcelable<Parcelable>(EXTRA_USER_KEY))
tabArgs.putString(EXTRA_SCREEN_NAME, args.getString(EXTRA_SCREEN_NAME))
}
pagerAdapter!!.addTab(cls = UserTimelineFragment::class.java, args = tabArgs, name = getString(R.string.statuses),
pagerAdapter.addTab(cls = UserTimelineFragment::class.java, args = tabArgs, name = getString(R.string.statuses),
icon = DrawableHolder.resource(R.drawable.ic_action_quote), type = TAB_TYPE_STATUSES, position = TAB_POSITION_STATUSES)
pagerAdapter!!.addTab(cls = UserMediaTimelineFragment::class.java, args = tabArgs, name = getString(R.string.media),
pagerAdapter.addTab(cls = UserMediaTimelineFragment::class.java, args = tabArgs, name = getString(R.string.media),
icon = DrawableHolder.resource(R.drawable.ic_action_gallery), type = TAB_TYPE_MEDIA, position = TAB_POSITION_MEDIA)
if (preferences.getBoolean(KEY_I_WANT_MY_STARS_BACK)) {
pagerAdapter!!.addTab(cls = UserFavoritesFragment::class.java, args = tabArgs, name = getString(R.string.favorites),
pagerAdapter.addTab(cls = UserFavoritesFragment::class.java, args = tabArgs, name = getString(R.string.favorites),
icon = DrawableHolder.resource(R.drawable.ic_action_star), type = TAB_TYPE_FAVORITES, position = TAB_POSITION_FAVORITES)
} else {
pagerAdapter!!.addTab(cls = UserFavoritesFragment::class.java, args = tabArgs, name = getString(R.string.likes),
pagerAdapter.addTab(cls = UserFavoritesFragment::class.java, args = tabArgs, name = getString(R.string.likes),
icon = DrawableHolder.resource(R.drawable.ic_action_heart), type = TAB_TYPE_FAVORITES, position = TAB_POSITION_FAVORITES)
}
}
private fun updateScrollOffset(offset: Int) {
val space = profileBannerSpace
val profileBannerView = profileBanner
val profileBirthdayBannerView = profileBirthdayBanner
val profileBannerContainer = profileBannerContainer
val spaceHeight = space!!.height
val spaceHeight = profileBannerSpace.height
val factor = TwidereMathUtils.clamp(if (spaceHeight == 0) 0f else offset / spaceHeight.toFloat(), 0f, 1f)
profileBannerContainer!!.translationY = (-offset).toFloat()
profileBannerView!!.translationY = (offset / 2).toFloat()
profileBirthdayBannerView!!.translationY = (offset / 2).toFloat()
profileBannerContainer.translationY = (-offset).toFloat()
profileBanner.translationY = (offset / 2).toFloat()
profileBirthdayBanner.translationY = (offset / 2).toFloat()
val activity = activity as BaseActivity
val statusBarColor = sArgbEvaluator.evaluate(factor, 0xA0000000.toInt(),
ThemeUtils.computeDarkColor(mPrimaryColorDark)) as Int
ThemeUtils.computeDarkColor(primaryColorDark)) as Int
val window = activity.window
userFragmentView!!.setStatusBarColor(statusBarColor)
userFragmentView.setStatusBarColor(statusBarColor)
ThemeUtils.setLightStatusBar(window, ThemeUtils.isLightColor(statusBarColor))
val stackedTabColor = mPrimaryColor
val stackedTabColor = primaryColor
val profileContentHeight = (profileNameContainer!!.height + profileDetailsContainer.height).toFloat()
@ -1387,14 +1382,13 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
tabOutlineAlphaFactor = 1f
}
if (mActionBarBackground != null) {
mActionBarBackground!!.setFactor(factor)
mActionBarBackground!!.setOutlineAlphaFactor(tabOutlineAlphaFactor)
actionBarBackground?.apply {
this.factor = factor
this.outlineAlphaFactor = tabOutlineAlphaFactor
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
windowOverlay!!.alpha = factor * tabOutlineAlphaFactor
// setCompatToolbarOverlayAlpha(activity, factor * tabOutlineAlphaFactor);
windowOverlay.alpha = factor * tabOutlineAlphaFactor
}
val currentTabColor = sArgbEvaluator.evaluate(tabOutlineAlphaFactor,
@ -1404,7 +1398,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
(tabBackground as ColorDrawable).color = currentTabColor
val tabItemIsDark = ThemeUtils.isLightColor(currentTabColor)
if (mPreviousTabItemIsDark == 0 || (if (tabItemIsDark) 1 else -1) != mPreviousTabItemIsDark) {
if (previousTabItemIsDark == 0 || (if (tabItemIsDark) 1 else -1) != previousTabItemIsDark) {
val tabContrastColor = ThemeUtils.getColorDependent(currentTabColor)
toolbarTabs.setIconColor(tabContrastColor)
toolbarTabs.setLabelColor(tabContrastColor)
@ -1416,15 +1410,15 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
}
toolbarTabs.updateAppearance()
}
mPreviousTabItemIsDark = if (tabItemIsDark) 1 else -1
previousTabItemIsDark = if (tabItemIsDark) 1 else -1
val currentActionBarColor = sArgbEvaluator.evaluate(factor, actionBarShadowColor,
stackedTabColor) as Int
val actionItemIsDark = ThemeUtils.isLightColor(currentActionBarColor)
if (mPreviousActionBarItemIsDark == 0 || (if (actionItemIsDark) 1 else -1) != mPreviousActionBarItemIsDark) {
if (previousActionBarItemIsDark == 0 || (if (actionItemIsDark) 1 else -1) != previousActionBarItemIsDark) {
ThemeUtils.applyToolbarItemColor(activity, toolbar, currentActionBarColor)
}
mPreviousActionBarItemIsDark = if (actionItemIsDark) 1 else -1
previousActionBarItemIsDark = if (actionItemIsDark) 1 else -1
updateTitleAlpha()
}
@ -1445,74 +1439,77 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
}
override var controlBarOffset: Float
get() {
return 0f
}
set(value) {//Ignore
}
get() = 0f
set(value) = Unit //Ignore
override val controlBarHeight: Int
get() {
return 0
}
get() = 0
override val shouldInitLoader: Boolean
get() = user != null
private class ActionBarDrawable(shadow: Drawable) : LayerDrawable(arrayOf(shadow, ActionBarColorDrawable.create(true))) {
private val mShadowDrawable: Drawable
private val mColorDrawable: ColorDrawable
private val shadowDrawable: Drawable
private val colorDrawable: ColorDrawable
private var alphaValue: Int = 0
var factor: Float = 0f
set(value) {
field = value
updateValue()
}
private var mFactor: Float = 0.toFloat()
var color: Int = 0
set(value) {
field = value
mColorDrawable.color = value
setFactor(mFactor)
colorDrawable.color = value
updateValue()
}
var outlineAlphaFactor: Float = 0f
set(value) {
field = value
updateValue()
}
private var mAlpha: Int = 0
private var mOutlineAlphaFactor: Float = 0.toFloat()
init {
mShadowDrawable = getDrawable(0)
mColorDrawable = getDrawable(1) as ColorDrawable
shadowDrawable = getDrawable(0)
colorDrawable = getDrawable(1) as ColorDrawable
alpha = 0xFF
setOutlineAlphaFactor(1f)
updateValue()
}
override fun setAlpha(alpha: Int) {
alphaValue = alpha
updateValue()
}
override fun getAlpha(): Int {
return alphaValue
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
override fun getOutline(outline: Outline) {
mColorDrawable.getOutline(outline)
outline.alpha = mFactor * mOutlineAlphaFactor * 0.99f
}
override fun setAlpha(alpha: Int) {
mAlpha = alpha
setFactor(mFactor)
colorDrawable.getOutline(outline)
outline.alpha = factor * outlineAlphaFactor * 0.99f
}
override fun getIntrinsicWidth(): Int {
return mColorDrawable.intrinsicWidth
return colorDrawable.intrinsicWidth
}
override fun getIntrinsicHeight(): Int {
return mColorDrawable.intrinsicHeight
return colorDrawable.intrinsicHeight
}
fun setFactor(f: Float) {
mFactor = f
val shadowAlpha = Math.round(mAlpha * TwidereMathUtils.clamp(1 - f, 0f, 1f))
mShadowDrawable.alpha = shadowAlpha
private fun updateValue() {
val shadowAlpha = Math.round(alpha * TwidereMathUtils.clamp(1 - factor, 0f, 1f))
shadowDrawable.alpha = shadowAlpha
val hasColor = color != 0
val colorAlpha = if (hasColor) Math.round(mAlpha * TwidereMathUtils.clamp(f, 0f, 1f)) else 0
mColorDrawable.alpha = colorAlpha
invalidateSelf()
}
fun setOutlineAlphaFactor(f: Float) {
mOutlineAlphaFactor = f
val colorAlpha = if (hasColor) Math.round(alpha * TwidereMathUtils.clamp(factor, 0f, 1f)) else 0
colorDrawable.alpha = colorAlpha
invalidateSelf()
}
@ -1574,7 +1571,6 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
return user.extras != null && TextUtils.equals(user_key.id, user.extras.unique_id) || TextUtils.equals(user_key.id, user.key.id)
}
class AddRemoveUserListDialogFragment : BaseDialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val lists = arguments.getParcelableArray(EXTRA_USER_LISTS).toTypedArray(ParcelableUserList.CREATOR)

View File

@ -20,11 +20,14 @@ import org.mariotaku.twidere.util.Utils
/**
* Created by mariotaku on 16/3/11.
*/
open class CreateUserBlockTask(context: Context) : AbsFriendshipOperationTask(context, FriendshipTaskEvent.Action.BLOCK), Constants {
open class CreateUserBlockTask(
context: Context,
val filterEverywhere: Boolean = false
) : AbsFriendshipOperationTask(context, FriendshipTaskEvent.Action.BLOCK), Constants {
@Throws(MicroBlogException::class)
override fun perform(twitter: MicroBlog, details: AccountDetails,
args: AbsFriendshipOperationTask.Arguments): User {
args: Arguments): User {
when (details.type) {
AccountType.FANFOU -> {
return twitter.createFanfouBlock(args.userKey.id)
@ -33,9 +36,8 @@ open class CreateUserBlockTask(context: Context) : AbsFriendshipOperationTask(co
return twitter.createBlock(args.userKey.id)
}
override fun succeededWorker(twitter: MicroBlog,
details: AccountDetails,
args: AbsFriendshipOperationTask.Arguments, user: ParcelableUser) {
override fun succeededWorker(twitter: MicroBlog, details: AccountDetails, args: Arguments,
user: ParcelableUser) {
val resolver = context.contentResolver
Utils.setLastSeen(context, args.userKey, -1)
for (uri in DataStoreUtils.STATUSES_URIS) {
@ -62,9 +64,13 @@ open class CreateUserBlockTask(context: Context) : AbsFriendshipOperationTask(co
values.put(CachedRelationships.FOLLOWING, false)
values.put(CachedRelationships.FOLLOWED_BY, false)
resolver.insert(CachedRelationships.CONTENT_URI, values)
if (filterEverywhere) {
DataStoreUtils.addToFilter(context, user, true)
}
}
override fun showSucceededMessage(params: AbsFriendshipOperationTask.Arguments, user: ParcelableUser) {
override fun showSucceededMessage(params: Arguments, user: ParcelableUser) {
val nameFirst = kPreferences[nameFirstKey]
val message = context.getString(R.string.blocked_user, manager.getDisplayName(user,
nameFirst))
@ -72,7 +78,7 @@ open class CreateUserBlockTask(context: Context) : AbsFriendshipOperationTask(co
}
override fun showErrorMessage(params: AbsFriendshipOperationTask.Arguments, exception: Exception?) {
override fun showErrorMessage(params: Arguments, exception: Exception?) {
Utils.showErrorMessage(context, R.string.action_blocking, exception, true)
}
}

View File

@ -37,8 +37,9 @@ class UpdateAccountInfoTask(private val context: Context) : AbstractTask<Pair<Ac
account.setAccountUser(am, user)
account.setAccountKey(am, user.key)
val accountKeyValues = ContentValues()
accountKeyValues.put(AccountSupportColumns.ACCOUNT_KEY, user.key.toString())
val accountKeyValues = ContentValues().apply {
put(AccountSupportColumns.ACCOUNT_KEY, user.key.toString())
}
val accountKeyWhere = Expression.equalsArgs(AccountSupportColumns.ACCOUNT_KEY).sql
val accountKeyWhereArgs = arrayOf(details.key.toString())

View File

@ -18,7 +18,6 @@ import org.mariotaku.twidere.model.account.cred.EmptyCredentials
import org.mariotaku.twidere.model.account.cred.OAuthCredentials
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts
import org.mariotaku.twidere.util.support.AccountManagerSupport
import java.util.*
/**
@ -27,10 +26,6 @@ import java.util.*
*/
@Suppress("deprecation")
fun migrateAccounts(am: AccountManager, db: SQLiteDatabase) {
am.getAccountsByType(ACCOUNT_TYPE).map { account ->
AccountManagerSupport.removeAccount(am, account, null, null, null)
}
val cur = db.query(Accounts.TABLE_NAME, Accounts.COLUMNS, null, null, null, null, null) ?: return
try {
val indices = ParcelableCredentialsCursorIndices(cur)

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/element_spacing_large">
<TextView
android:id="@+id/confirmMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"
tools:text="@string/block_user_confirm_message"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_normal">
<CheckBox
android:id="@+id/filterEverywhereToggle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/filter_everywhere"
android:textAppearance="?android:textAppearanceMedium"/>
<org.mariotaku.twidere.view.IconActionButton
android:id="@+id/filterEverywhereHelp"
android:layout_width="@dimen/button_size_content_card_action"
android:layout_height="@dimen/button_size_content_card_action"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginStart="@dimen/element_spacing_normal"
android:layout_weight="0"
android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/ic_action_info"
app:iabColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/element_spacing_large">
<TextView
android:id="@+id/confirmMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"
tools:text="@string/filter_user_confirm_message"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_normal">
<CheckBox
android:id="@+id/filterEverywhereToggle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/filter_everywhere"
android:textAppearance="?android:textAppearanceMedium"/>
<org.mariotaku.twidere.view.IconActionButton
android:id="@+id/filterEverywhereHelp"
android:layout_width="@dimen/button_size_content_card_action"
android:layout_height="@dimen/button_size_content_card_action"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginStart="@dimen/element_spacing_normal"
android:layout_weight="0"
android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/ic_action_info"
app:iabColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TextView
android:id="@android:id/text1"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:tag="tint_background|accent_color"
android:textAppearance="?android:attr/textAppearanceListItemSmall"/>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TwoLineListItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeight"
android:mode="twoLine"
android:paddingBottom="2dip"
android:paddingTop="2dip"
android:tag="tint_background|accent_color">
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceListItem"/>
<TextView
android:id="@android:id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@android:id/text1"
android:layout_alignStart="@android:id/text1"
android:layout_below="@android:id/text1"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</TwoLineListItem>

View File

@ -49,7 +49,6 @@
android:title="@string/enable_retweets"/>
<item
android:id="@id/add_to_filter"
android:checkable="true"
android:icon="@drawable/ic_action_speaker_muted"
android:title="@string/add_to_filter"/>
<item

View File

@ -302,6 +302,8 @@
<string name="action_refreshing_direct_messages">refreshing direct messages</string>
<string name="action_favoriting">favoriting</string>
<string name="action_unfavoriting">unfavoriting</string>
<string name="action_liking">liking</string>
<string name="action_cancelling_like">cancelling like</string>
<string name="action_deleting">deleting</string>
<string name="action_updating_profile">updating profile</string>
<string name="action_updating_profile_image">updating profile image</string>
@ -378,6 +380,8 @@
<string name="status_deleted">Tweet deleted.</string>
<string name="status_favorited">Tweet favorited.</string>
<string name="status_unfavorited">Tweet unfavorited.</string>
<string name="status_liked">Tweet liked.</string>
<string name="status_like_removed">Like removed.</string>
<string name="status_retweeted">Retweeted.</string>
<string name="retweet_cancelled">Retweet cancelled.</string>
<string name="direct_message_sent">Direct message sent.</string>
@ -468,7 +472,8 @@
<string name="keyword_filter_name">Keyword: <xliff:g id="name">%s</xliff:g></string>
<string name="source_filter_name">Source: <xliff:g id="name">%s</xliff:g></string>
<string name="block_user">Block <xliff:g id="name">%s</xliff:g></string>
<string name="block_user_confirm_message">Block <xliff:g id="name">%s</xliff:g>? This user won\'t be able to follow you, mention you or send you direct messages.</string>
<string name="block_user_confirm_message">Block <xliff:g example="Username" id="name">%s</xliff:g>? This user won\'t be able to follow you, mention you or send you direct messages.</string>
<string name="filter_user_confirm_message">Add <xliff:g example="Username" id="name">%s</xliff:g> to filter?</string>
<string name="unfollow_user">Unfollow <xliff:g id="name">%s</xliff:g></string>
<string name="unfollow_user_confirm_message">Unfollow <xliff:g id="name">%s</xliff:g>? You will no longer see tweets from this user.</string>
<string name="delete_user_list">Delete list <xliff:g id="name">%s</xliff:g></string>
@ -818,4 +823,7 @@
<string name="pinned_status">Pinned tweet</string>
<string name="add_or_remove_from_list">Add or remove from list</string>
<string name="title_extra_features">Extra features</string>
<string name="filter_everywhere">Filter everywhere</string>
<string name="filter_everywhere_description">These will be filtered in Twidere:\n &#xb7;User\'s tweets\n &#xb7;Tweets mentioning this user\n &#xb7;Retweets/Quotes of this user</string>
<string name="message_toast_added_to_filter">Added to filter.</string>
</resources>