diff --git a/twidere/src/main/java/org/mariotaku/dynamicgridview/DraggableArrayAdapter.java b/twidere/src/main/java/org/mariotaku/dynamicgridview/DraggableArrayAdapter.java index 0cfc0084b..39e3dc9ef 100644 --- a/twidere/src/main/java/org/mariotaku/dynamicgridview/DraggableArrayAdapter.java +++ b/twidere/src/main/java/org/mariotaku/dynamicgridview/DraggableArrayAdapter.java @@ -27,96 +27,95 @@ import java.util.List; public class DraggableArrayAdapter extends ArrayAdapter implements DraggableAdapter { - final int INVALID_ID = -1; + final int INVALID_ID = -1; - private final HashMap mIdMap = new HashMap(); + private final HashMap mIdMap = new HashMap(); - public DraggableArrayAdapter(final Context context, final int layoutRes) { - this(context, layoutRes, null); - } + public DraggableArrayAdapter(final Context context, final int layoutRes) { + this(context, layoutRes, null); + } - public DraggableArrayAdapter(final Context context, final int layoutRes, final Collection collection) { - super(context, layoutRes, collection); - rebuildIdMap(); - } + public DraggableArrayAdapter(final Context context, final int layoutRes, final Collection collection) { + super(context, layoutRes, collection); + rebuildIdMap(); + } - @Override - public void add(final T item) { - super.add(item); - rebuildIdMap(); - } + @Override + public void add(final T item) { + super.add(item); + rebuildIdMap(); + } - @Override - public void addAll(final Collection collection) { - super.addAll(collection); - rebuildIdMap(); - } + @Override + public void addAll(final Collection collection) { + super.addAll(collection); + rebuildIdMap(); + } - @Override - public void clear() { - super.clear(); - rebuildIdMap(); - } + @Override + public void clear() { + super.clear(); + rebuildIdMap(); + } - @Override - public long getItemId(final int position) { - if (position < 0 || position >= mIdMap.size()) return INVALID_ID; - final T item = getItem(position); - return mIdMap.get(item); - } + @Override + public long getItemId(final int position) { + if (position < 0 || position >= mIdMap.size()) return INVALID_ID; + final T item = getItem(position); + return mIdMap.get(item); + } - @Override - public boolean hasStableIds() { - return true; - } + @Override + public boolean hasStableIds() { + return true; + } - @Override - public boolean remove(final int position) { - final boolean result = super.remove(position); - rebuildIdMap(); - return result; - } + public void removeAt(final int position) { + super.removeAt(position); + rebuildIdMap(); + } - @Override - public void removeAll(final List collection) { - super.removeAll(collection); - rebuildIdMap(); - } + @Override + public void removeAll(final Collection collection) { + super.removeAll(collection); + rebuildIdMap(); + } - @Override - public void reorderElements(final int position, final int newPosition) { - final List objects = mData; + @Override + public void reorderElements(final int position, final int newPosition) { + final List objects = getObjects(); - T previous = objects.get(position); - final int iterator = newPosition < position ? 1 : -1; - final int afterPosition = position + iterator; - for (int cellPosition = newPosition; cellPosition != afterPosition; cellPosition += iterator) { - final T tmp = objects.get(cellPosition); - objects.set(cellPosition, previous); - previous = tmp; - } - notifyDataSetChanged(); - } + T previous = objects.get(position); + final int iterator = newPosition < position ? 1 : -1; + final int afterPosition = position + iterator; + for (int cellPosition = newPosition; cellPosition != afterPosition; cellPosition += iterator) { + final T tmp = objects.get(cellPosition); + objects.set(cellPosition, previous); + previous = tmp; + } + notifyDataSetChanged(); + } - @Override - public void sort(final Comparator comparator) { - super.sort(comparator); - rebuildIdMap(); - } + @Override + public void sort(final Comparator comparator) { + super.sort(comparator); + rebuildIdMap(); + } - @Override - public void swapElements(final int position, final int newPosition) { - final List objects = mData; - final T temp = objects.get(position); - objects.set(position, objects.get(newPosition)); - objects.set(newPosition, temp); - notifyDataSetChanged(); - } + @Override + public void swapElements(final int position, final int newPosition) { + final List objects = getObjects(); + final T temp = objects.get(position); + objects.set(position, objects.get(newPosition)); + objects.set(newPosition, temp); + notifyDataSetChanged(); + } - private void rebuildIdMap() { - mIdMap.clear(); - for (int i = 0, j = mData.size(); i < j; ++i) { - mIdMap.put(mData.get(i), i); - } - } + private void rebuildIdMap() { + mIdMap.clear(); + final List objects = getObjects(); + for (int i = 0, j = objects.size(); i < j; ++i) { + mIdMap.put(objects.get(i), i); + } + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java index c6b9ad4b0..a3052bf8c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java @@ -45,12 +45,11 @@ import android.os.Parcelable; import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; -import android.support.v4.util.LongSparseArray; -import android.support.v7.widget.RecyclerView.ViewHolder; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.Log; +import android.util.SparseBooleanArray; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -60,9 +59,13 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; import android.widget.EditText; import android.widget.GridView; import android.widget.ImageView; +import android.widget.ListView; import android.widget.ProgressBar; import android.widget.ScrollView; import android.widget.TextView; @@ -73,9 +76,9 @@ import com.nostra13.universalimageloader.utils.IoUtils; import com.twitter.Extractor; import org.mariotaku.dynamicgridview.DraggableArrayAdapter; +import org.mariotaku.menucomponent.internal.widget.IListPopupWindow; import org.mariotaku.menucomponent.widget.MenuBar; import org.mariotaku.menucomponent.widget.MenuBar.MenuBarListener; -import org.mariotaku.menucomponent.widget.PopupMenu; import org.mariotaku.twidere.R; import org.mariotaku.twidere.adapter.BaseArrayAdapter; import org.mariotaku.twidere.app.TwidereApplication; @@ -105,7 +108,6 @@ import org.mariotaku.twidere.util.accessor.ViewAccessor; import org.mariotaku.twidere.view.ColorLabelFrameLayout; import org.mariotaku.twidere.view.StatusTextCountView; import org.mariotaku.twidere.view.holder.StatusViewHolder; -import org.mariotaku.twidere.view.iface.IColorLabelView; import java.io.File; import java.io.FileOutputStream; @@ -115,6 +117,7 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.TreeSet; @@ -147,7 +150,7 @@ import static org.mariotaku.twidere.util.Utils.showErrorMessage; import static org.mariotaku.twidere.util.Utils.showMenuItemToast; public class ComposeActivity extends BaseSupportDialogActivity implements TextWatcher, LocationListener, - MenuBarListener, OnClickListener, OnEditorActionListener, OnLongClickListener { + MenuBarListener, OnClickListener, OnEditorActionListener, OnLongClickListener, OnItemClickListener { private static final String FAKE_IMAGE_LINK = "https://www.example.com/fake_image.jpg"; @@ -170,20 +173,18 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa private ContentResolver mResolver; private AsyncTask mTask; - private PopupMenu mPopupMenu; + private IListPopupWindow mAccountSelectorPopup; private TextView mTitleView, mSubtitleView; private GridView mMediasPreviewGrid; private MenuBar mMenuBar; - private IColorLabelView mColorIndicator; private EditText mEditText; private ProgressBar mProgress; private View mSendView; private StatusTextCountView mSendTextCountView; - private ColorLabelFrameLayout mSelectAccount; + private ColorLabelFrameLayout mSelectAccountButton; private MediaPreviewAdapter mMediaPreviewAdapter; - private AccountSelectorAdapter mAccountSelectorAdapter; private boolean mIsPossiblySensitive, mShouldSaveAccounts; @@ -417,7 +418,16 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa break; } case R.id.select_account: { - Toast.makeText(this, "Select account", Toast.LENGTH_SHORT).show(); + if (!mAccountSelectorPopup.isShowing()) { + mAccountSelectorPopup.show(); + } + final ListView listView = mAccountSelectorPopup.getListView(); + listView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); + listView.setOnItemClickListener(this); + for (int i = 0, j = listView.getCount(); i < j; i++) { + final long itemId = listView.getItemIdAtPosition(i); + listView.setItemChecked(i, ArrayUtils.contains(mSendAccountIds, itemId)); + } break; } } @@ -427,7 +437,6 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa public void onContentChanged() { super.onContentChanged(); findViewById(R.id.close).setOnClickListener(this); - mColorIndicator = (IColorLabelView) findViewById(R.id.accounts_color); mEditText = (EditText) findViewById(R.id.edit_text); mTitleView = (TextView) findViewById(R.id.actionbar_title); mSubtitleView = (TextView) findViewById(R.id.actionbar_subtitle); @@ -438,7 +447,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa final View composeBottomBar = findViewById(R.id.compose_bottombar); mSendView = composeBottomBar.findViewById(R.id.send); mSendTextCountView = (StatusTextCountView) mSendView.findViewById(R.id.status_text_count); - mSelectAccount = (ColorLabelFrameLayout) composeActionBar.findViewById(R.id.select_account); + mSelectAccountButton = (ColorLabelFrameLayout) composeActionBar.findViewById(R.id.select_account); ViewAccessor.setBackground(findViewById(R.id.compose_content), getWindowContentOverlayForCompose(this)); ViewAccessor.setBackground(composeActionBar, getActionBarBackground(this, getCurrentThemeResourceId())); } @@ -455,24 +464,6 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa return false; } -// @Override -// public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { -// if (isSingleAccount()) return; -// final boolean selected = !view.isActivated(); -// final Account account = mAccountSelectorAdapter.getItem(position); -// mAccountSelectorAdapter.setAccountSelected(account.account_id, selected); -// mSendAccountIds = mAccountSelectorAdapter.getSelectedAccountIds(); -// updateAccountSelection(); -// } -// -// @Override -// public boolean onItemLongClick(final AdapterView parent, final View view, final int position, final long id) { -// final Account account = mAccountSelectorAdapter.getItem(position); -// final String displayName = getDisplayName(this, account.account_id, account.name, account.screen_name); -// showMenuItemToast(view, displayName, true); -// return true; -// } - @Override public void onLocationChanged(final Location location) { if (mRecentLocation == null) { @@ -576,7 +567,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa mTwitterWrapper = getTwidereApplication().getTwitterWrapper(); mResolver = getContentResolver(); mValidator = new TwidereValidator(this); - setContentView(getLayoutInflater().inflate(R.layout.activity_compose, null)); + setContentView(R.layout.activity_compose); setProgressBarIndeterminateVisibility(false); setFinishOnTouchOutside(false); mAccountIds = getAccountIds(this); @@ -591,11 +582,16 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa mMenuBar.setMenuBarListener(this); mEditText.setOnEditorActionListener(mPreferences.getBoolean(KEY_QUICK_SEND, false) ? this : null); mEditText.addTextChangedListener(this); - mAccountSelectorAdapter = new AccountSelectorAdapter(this); - mAccountSelectorAdapter.addAll(Account.getAccountsList(this, false)); - mSelectAccount.setOnClickListener(this); -// mAccountSelector.setOnItemClickListener(this); -// mAccountSelector.setOnItemLongClickListener(this); + final AccountSelectorAdapter accountAdapter = new AccountSelectorAdapter(this); + accountAdapter.addAll(Account.getAccountsList(this, false)); + mAccountSelectorPopup = IListPopupWindow.InstanceHelper.getInstance(mMenuBar.getPopupContext()); + mAccountSelectorPopup.setModal(true); + mAccountSelectorPopup.setContentWidth(getResources().getDimensionPixelSize(R.dimen.mc__popup_window_width)); + mAccountSelectorPopup.setAdapter(accountAdapter); + mAccountSelectorPopup.setAnchorView(mSelectAccountButton); + + mSelectAccountButton.setOnClickListener(this); + mSelectAccountButton.setOnLongClickListener(this); mMediaPreviewAdapter = new MediaPreviewAdapter(this); mMediasPreviewGrid.setAdapter(mMediaPreviewAdapter); @@ -668,8 +664,8 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa @Override protected void onStop() { - if (mPopupMenu != null) { - mPopupMenu.dismiss(); + if (mAccountSelectorPopup != null && mAccountSelectorPopup.isShowing()) { + mAccountSelectorPopup.dismiss(); } mLocationManager.removeUpdates(this); super.onStop(); @@ -929,22 +925,6 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa return true; } - private void setCommonMenu(final Menu menu) { - final boolean hasMedia = hasMedia(); - // final MenuItem itemAddImageSubmenu = - // menu.findItem(R.id.add_image_submenu); - // if (itemAddImageSubmenu != null) { - // final Drawable iconAddImage = itemAddImageSubmenu.getIcon(); - // iconAddImage.mutate(); - // if (hasMedia) { - // iconAddImage.setColorFilter(activatedColor, Mode.SRC_ATOP); - // } else { - // iconAddImage.clearColorFilter(); - // } - // } - - } - private boolean setComposeTitle(final Intent intent) { final String action = intent.getAction(); if (INTENT_ACTION_REPLY.equals(action)) { @@ -1046,11 +1026,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa editor.putString(KEY_COMPOSE_ACCOUNTS, ArrayUtils.toString(mSendAccountIds, ',', false)); editor.apply(); } - mAccountSelectorAdapter.clearAccountSelection(); - for (final long accountId : mSendAccountIds) { - mAccountSelectorAdapter.setAccountSelected(accountId, true); - } - mSelectAccount.drawEnd(getAccountColors(this, mSendAccountIds)); + mSelectAccountButton.drawEnd(getAccountColors(this, mSendAccountIds)); } private void updateMediasPreview() { @@ -1129,6 +1105,19 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa } + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final ListView listView = (ListView) parent; + final SparseBooleanArray checkedPositions = listView.getCheckedItemPositions(); + mSendAccountIds = new long[listView.getCheckedItemCount()]; + for (int i = 0, j = listView.getCount(), k = 0; i < j; i++) { + if (checkedPositions.get(i)) { + mSendAccountIds[k++] = listView.getItemIdAtPosition(i); + } + } + updateAccountSelection(); + } + public static class RetweetProtectedStatusWarnFragment extends BaseSupportDialogFragment implements DialogInterface.OnClickListener { @@ -1287,48 +1276,29 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa private static class AccountSelectorAdapter extends BaseArrayAdapter { - private final LongSparseArray mAccountSelectStates = new LongSparseArray<>(); - - public AccountSelectorAdapter(final Context context) { - super(context, R.layout.adapter_item_compose_account); + super(context, android.R.layout.simple_list_item_multiple_choice); } - public void clearAccountSelection() { - mAccountSelectStates.clear(); - notifyDataSetChanged(); + @Override + public long getItemId(int position) { + return super.getItem(position).account_id; } - public void setAccountSelected(final long accountId, final boolean selected) { - mAccountSelectStates.put(accountId, selected); - notifyDataSetChanged(); + @Override + public boolean hasStableIds() { + return true; } @Override public View getView(int position, View convertView, ViewGroup parent) { final View view = super.getView(position, convertView, parent); - final ImageView icon = (ImageView) view.findViewById(android.R.id.icon); final Account account = getItem(position); - final ImageLoaderWrapper loader = getImageLoader(); - loader.displayProfileImage(icon, account.profile_image_url); + final TextView text1 = (TextView) view.findViewById(android.R.id.text1); + text1.setText(Utils.getAccountDisplayName(getContext(), account.account_id, isDisplayNameFirst())); return view; } - - } - - - private static class AccountAvatarHolder extends ViewHolder { - - private final ImageView icon; - - public AccountAvatarHolder(View itemView) { - super(itemView); - icon = (ImageView) itemView.findViewById(android.R.id.icon); - } - - public void setAccount(ImageLoaderWrapper loader, Account account, LongSparseArray states) { - } } private static class AddBitmapTask extends AddMediaTask { @@ -1516,5 +1486,8 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa return view; } + public List getAsList() { + return Collections.unmodifiableList(getObjects()); + } } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java index 80831594f..b7efd0b2e 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java @@ -37,6 +37,7 @@ import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.util.Log; import android.util.SparseBooleanArray; import android.view.ActionMode; import android.view.Menu; @@ -312,10 +313,16 @@ public class DraftsActivity extends BaseSupportActivity implements LoaderCallbac final int idxMedias = c.getColumnIndex(Drafts.MEDIAS); c.moveToFirst(); while (!c.isAfterLast()) { - for (final ParcelableMediaUpdate media : ParcelableMediaUpdate.fromJSONString(c.getString(idxMedias))) { - final Uri uri = Uri.parse(media.uri); - if ("file".equals(uri.getScheme()) && uri.getPath() != null) { - new File(uri.getPath()).delete(); + final ParcelableMediaUpdate[] medias = ParcelableMediaUpdate.fromJSONString(c.getString(idxMedias)); + if (medias != null) { + for (final ParcelableMediaUpdate media : medias) { + final Uri uri = Uri.parse(media.uri); + if ("file".equals(uri.getScheme())) { + final File file = new File(uri.getPath()); + if (!file.delete()) { + Log.w(LOGTAG, String.format("Unable to delete %s", file)); + } + } } } c.moveToNext(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java index 7f532d970..704eb5512 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java @@ -74,19 +74,6 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons super.bindView(view, context, cursor); } - @Override - public long getItemId(final int position) { - final Cursor c = getCursor(); - if (c == null || c.isClosed()) return -1; - c.moveToPosition(position); - return c.getLong(mAccountIdIdx); - } - - @Override - public boolean hasStableIds() { - return true; - } - @Override public View newView(final Context context, final Cursor cursor, final ViewGroup parent) { final View view = super.newView(context, cursor, parent); diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayAdapter.java index 0f64e1ec8..180348193 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayAdapter.java @@ -1,20 +1,17 @@ /* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2014 Mariotaku Lee - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Copyright (C) 2006 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. */ package org.mariotaku.twidere.adapter; @@ -24,117 +21,469 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.Filter; +import android.widget.Filterable; +import android.widget.TextView; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; -public class ArrayAdapter extends BaseAdapter { +/** + * A concrete BaseAdapter that is backed by an array of arbitrary + * objects. By default this class expects that the provided resource id references + * a single TextView. If you want to use a more complex layout, use the constructors that + * also takes a field id. That field id should reference a TextView in the larger layout + * resource. + *

+ *

However the TextView is referenced, it will be filled with the toString() of each object in + * the array. You can add lists or arrays of custom objects. Override the toString() method + * of your objects to determine what text will be displayed for the item in the list. + *

+ *

To use something other than TextViews for the array display, for instance, ImageViews, + * or to have some of data besides toString() results fill the views, + * override {@link #getView(int, View, ViewGroup)} to return the type of view you want. + */ +public class ArrayAdapter extends BaseAdapter implements Filterable { + /** + * Contains the list of objects that represent the data of this ArrayAdapter. + * The content of this list is referred to as "the array" in the documentation. + */ + private List mObjects; - private final LayoutInflater mInflater; - private final int mLayoutRes; - private int mDropDownLayoutRes; + /** + * Lock used to modify the content of {@link #mObjects}. Any write operation + * performed on the array should be synchronized on this lock. This lock is also + * used by the filter (see {@link #getFilter()} to make a synchronized copy of + * the original array of data. + */ + private final Object mLock = new Object(); - protected final ArrayList mData = new ArrayList(); - private final Context mContext; + /** + * The resource indicating what views to inflate to display the content of this + * array adapter. + */ + private int mResource; - public ArrayAdapter(final Context context, final int layoutRes) { - this(context, layoutRes, null); - } + /** + * The resource indicating what views to inflate to display the content of this + * array adapter in a drop down widget. + */ + private int mDropDownResource; - public ArrayAdapter(final Context context, final int layoutRes, final Collection collection) { - mContext = context; - mInflater = LayoutInflater.from(context); - mLayoutRes = layoutRes; - if (collection != null) { - addAll(collection); - } - } + /** + * Indicates whether or not {@link #notifyDataSetChanged()} must be called whenever + * {@link #mObjects} is modified. + */ + private boolean mNotifyOnChange = true; - public void add(final T item) { - if (item == null) return; - mData.add(item); - notifyDataSetChanged(); - } + private Context mContext; - public void addAll(final Collection collection) { - mData.addAll(collection); - notifyDataSetChanged(); - } + // A copy of the original mObjects array, initialized from and then used instead as soon as + // the mFilter ArrayFilter is used. mObjects will then only contain the filtered values. + private ArrayList mOriginalValues; + private ArrayFilter mFilter; - public void clear() { - mData.clear(); - notifyDataSetChanged(); - } + private LayoutInflater mInflater; - public T findItem(final long id) { - for (int i = 0, count = getCount(); i < count; i++) { - if (getItemId(i) == id) return getItem(i); - } - return null; - } - public int findItemPosition(final long id) { - for (int i = 0, count = getCount(); i < count; i++) { - if (getItemId(i) == id) return i; - } - return -1; - } + /** + * Constructor + * + * @param context The current context. + * @param resource The resource ID for a layout file containing a layout to use when + * instantiating views. + */ + public ArrayAdapter(Context context, int resource) { + init(context, resource, new ArrayList()); + } - public List getAsList() { - return Collections.unmodifiableList(mData); - } + /** + * Constructor + * + * @param context The current context. + * @param resource The resource ID for a layout file containing a layout to use when + * instantiating views. + * @param objects The objects to represent in the ListView. + */ + public ArrayAdapter(Context context, int resource, T[] objects) { + init(context, resource, Arrays.asList(objects)); + } - public Context getContext() { - return mContext; - } + /** + * Constructor + * + * @param context The current context. + * @param resource The resource ID for a layout file containing a layout to use when + * instantiating views. + * @param objects The objects to represent in the ListView. + */ + public ArrayAdapter(Context context, int resource, Collection objects) { + init(context, resource, objects); + } - @Override - public int getCount() { - return mData.size(); - } + /** + * Adds the specified object at the end of the array. + * + * @param object The object to add at the end of the array. + */ + public void add(T object) { + synchronized (mLock) { + if (mOriginalValues != null) { + mOriginalValues.add(object); + } else { + mObjects.add(object); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - @Override - public View getDropDownView(final int position, final View convertView, final ViewGroup parent) { - final int layoutRes = mDropDownLayoutRes > 0 ? mDropDownLayoutRes : mLayoutRes; - return convertView != null ? convertView : mInflater.inflate(layoutRes, parent, false); - } + /** + * Adds the specified Collection at the end of the array. + * + * @param collection The Collection to add at the end of the array. + */ + public void addAll(Collection collection) { + synchronized (mLock) { + if (mOriginalValues != null) { + mOriginalValues.addAll(collection); + } else { + mObjects.addAll(collection); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - @Override - public T getItem(final int position) { - return mData.get(position); - } + /** + * Adds the specified items at the end of the array. + * + * @param items The items to add at the end of the array. + */ + public void addAll(T... items) { + synchronized (mLock) { + if (mOriginalValues != null) { + Collections.addAll(mOriginalValues, items); + } else { + Collections.addAll(mObjects, items); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - @Override - public long getItemId(final int position) { - return position; - } + /** + * Inserts the specified object at the specified index in the array. + * + * @param object The object to insert into the array. + * @param index The index at which the object must be inserted. + */ + public void insert(T object, int index) { + synchronized (mLock) { + if (mOriginalValues != null) { + mOriginalValues.add(index, object); + } else { + mObjects.add(index, object); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - return convertView != null ? convertView : mInflater.inflate(mLayoutRes, parent, false); - } + /** + * Removes the specified object from the array. + * + * @param object The object to remove. + */ + public void remove(T object) { + synchronized (mLock) { + if (mOriginalValues != null) { + mOriginalValues.remove(object); + } else { + mObjects.remove(object); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - public boolean remove(final int position) { - final boolean ret = mData.remove(position) != null; - notifyDataSetChanged(); - return ret; - } + public void removeAt(int position) { + synchronized (mLock) { + if (mOriginalValues != null) { + mOriginalValues.remove(position); + } else { + mObjects.remove(position); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - public void removeAll(final List collection) { - mData.removeAll(collection); - notifyDataSetChanged(); - } + /** + * Remove all elements from the list. + */ + public void clear() { + synchronized (mLock) { + if (mOriginalValues != null) { + mOriginalValues.clear(); + } else { + mObjects.clear(); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - public void setDropDownViewResource(final int layoutRes) { - mDropDownLayoutRes = layoutRes; - } + /** + * Sorts the content of this adapter using the specified comparator. + * + * @param comparator The comparator used to sort the objects contained + * in this adapter. + */ + public void sort(Comparator comparator) { + synchronized (mLock) { + if (mOriginalValues != null) { + Collections.sort(mOriginalValues, comparator); + } else { + Collections.sort(mObjects, comparator); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } - public void sort(final Comparator comparator) { - Collections.sort(mData, comparator); - notifyDataSetChanged(); - } + /** + * {@inheritDoc} + */ + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + mNotifyOnChange = true; + } + /** + * Control whether methods that change the list ({@link #add}, + * {@link #insert}, {@link #remove}, {@link #clear}) automatically call + * {@link #notifyDataSetChanged}. If set to false, caller must + * manually call notifyDataSetChanged() to have the changes + * reflected in the attached view. + *

+ * The default is true, and calling notifyDataSetChanged() + * resets the flag to true. + * + * @param notifyOnChange if true, modifications to the list will + * automatically call {@link + * #notifyDataSetChanged} + */ + public void setNotifyOnChange(boolean notifyOnChange) { + mNotifyOnChange = notifyOnChange; + } + + private void init(Context context, int resource, Collection objects) { + mContext = context; + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mResource = mDropDownResource = resource; + if (objects != null) { + mObjects = new ArrayList<>(objects); + } else { + mObjects = new ArrayList<>(); + } + } + + /** + * Returns the context associated with this array adapter. The context is used + * to create views from the resource passed to the constructor. + * + * @return The Context associated with this adapter. + */ + public Context getContext() { + return mContext; + } + + /** + * {@inheritDoc} + */ + public int getCount() { + return mObjects.size(); + } + + /** + * {@inheritDoc} + */ + public T getItem(int position) { + return mObjects.get(position); + } + + /** + * Returns the position of the specified item in the array. + * + * @param item The item to retrieve the position of. + * @return The position of the specified item. + */ + public int getPosition(T item) { + return mObjects.indexOf(item); + } + + /** + * {@inheritDoc} + */ + public long getItemId(int position) { + return position; + } + + /** + * {@inheritDoc} + */ + public View getView(int position, View convertView, ViewGroup parent) { + return createViewFromResource(position, convertView, parent, mResource); + } + + private View createViewFromResource(int position, View convertView, ViewGroup parent, + int resource) { + View view; + TextView text; + + if (convertView == null) { + view = mInflater.inflate(resource, parent, false); + } else { + view = convertView; + } + + return view; + } + + /** + *

Sets the layout resource to create the drop down views.

+ * + * @param resource the layout resource defining the drop down views + * @see #getDropDownView(int, android.view.View, android.view.ViewGroup) + */ + public void setDropDownViewResource(int resource) { + this.mDropDownResource = resource; + } + + /** + * {@inheritDoc} + */ + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + return createViewFromResource(position, convertView, parent, mDropDownResource); + } + + /** + * Creates a new ArrayAdapter from external resources. The content of the array is + * obtained through {@link android.content.res.Resources#getTextArray(int)}. + * + * @param context The application's environment. + * @param textArrayResId The identifier of the array to use as the data source. + * @param textViewResId The identifier of the layout used to create views. + * @return An ArrayAdapter. + */ + public static ArrayAdapter createFromResource(Context context, + int textArrayResId, int textViewResId) { + CharSequence[] strings = context.getResources().getTextArray(textArrayResId); + return new ArrayAdapter<>(context, textViewResId, strings); + } + + /** + * {@inheritDoc} + */ + public Filter getFilter() { + if (mFilter == null) { + mFilter = new ArrayFilter(); + } + return mFilter; + } + + protected List getObjects() { + return mObjects; + } + + public int findItemPosition(long id) { + for (int i = 0, j = getCount(); i < j; i++) { + if (getItemId(i) == id) return i; + } + return -1; + } + + public void removeAll(Collection collection) { + synchronized (mLock) { + if (mOriginalValues != null) { + mOriginalValues.removeAll(collection); + } else { + mObjects.removeAll(collection); + } + } + if (mNotifyOnChange) notifyDataSetChanged(); + } + + /** + *

An array filter constrains the content of the array adapter with + * a prefix. Each item that does not start with the supplied prefix + * is removed from the list.

+ */ + private class ArrayFilter extends Filter { + @Override + protected FilterResults performFiltering(CharSequence prefix) { + FilterResults results = new FilterResults(); + + if (mOriginalValues == null) { + synchronized (mLock) { + mOriginalValues = new ArrayList<>(mObjects); + } + } + + if (prefix == null || prefix.length() == 0) { + ArrayList list; + synchronized (mLock) { + list = new ArrayList<>(mOriginalValues); + } + results.values = list; + results.count = list.size(); + } else { + String prefixString = prefix.toString().toLowerCase(); + + ArrayList values; + synchronized (mLock) { + values = new ArrayList<>(mOriginalValues); + } + + final int count = values.size(); + final ArrayList newValues = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + final T value = values.get(i); + final String valueText = value.toString().toLowerCase(); + + // First match against the whole, non-splitted value + if (valueText.startsWith(prefixString)) { + newValues.add(value); + } else { + final String[] words = valueText.split(" "); + final int wordCount = words.length; + + // Start at index 0, in case valueText starts with space(s) + for (int k = 0; k < wordCount; k++) { + if (words[k].startsWith(prefixString)) { + newValues.add(value); + break; + } + } + } + } + + results.values = newValues; + results.count = newValues.size(); + } + + return results; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + //noinspection unchecked + mObjects = (List) results.values; + if (results.count > 0) { + notifyDataSetChanged(); + } else { + notifyDataSetInvalidated(); + } + } + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java index c36771ecc..dbbb4d7c0 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java @@ -169,7 +169,7 @@ public class ParcelableUserListsAdapter extends BaseArrayAdapter imp } if (data == null) return; for (final ParcelableUser user : data) { - if (clear_old || findItem(user.id) == null) { + if (clear_old || findItemPosition(user.id) < 0) { add(user); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.java index 2cff260d7..ae15514dd 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.java @@ -92,7 +92,7 @@ public class SimpleParcelableUserListsAdapter extends BaseArrayAdapter positions = mAdapter.getCursorPositions(); + final Cursor c = mAdapter.getCursor(); + if (positions != null && c != null && !c.isClosed()) { + final int idIdx = c.getColumnIndex(Accounts._ID); + for (int i = 0, j = positions.size(); i < j; i++) { + c.moveToPosition(positions.get(i)); + final long id = c.getLong(idIdx); + final ContentValues values = new ContentValues(); + values.put(Accounts.SORT_POSITION, i); + final Where where = Where.equals(Accounts._ID, id); + cr.update(Accounts.CONTENT_URI, values, where.getSQL(), null); + } + } + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseSupportListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseSupportListFragment.java index ce085e232..7d60cec0c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseSupportListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseSupportListFragment.java @@ -34,7 +34,6 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; @@ -58,6 +57,8 @@ import org.mariotaku.twidere.util.ListScrollDistanceCalculator.ScrollDistanceLis import org.mariotaku.twidere.util.MultiSelectManager; import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.Utils; +import org.mariotaku.twidere.view.ExtendedFrameLayout; +import org.mariotaku.twidere.view.iface.IExtendedView.TouchInterceptor; import static android.support.v4.app.ListFragmentTrojan.INTERNAL_EMPTY_ID; import static android.support.v4.app.ListFragmentTrojan.INTERNAL_LIST_CONTAINER_ID; @@ -169,10 +170,16 @@ public class BaseSupportListFragment extends ListFragment implements IBaseFragme } - private final OnTouchListener mInternalOnTouchListener = new OnTouchListener() { + private final TouchInterceptor mInternalOnTouchListener = new TouchInterceptor() { + @Override - public boolean onTouch(View v, MotionEvent event) { - switch (event.getAction()) { + public boolean dispatchTouchEvent(View view, MotionEvent event) { + return false; + } + + @Override + public boolean onInterceptTouchEvent(View view, MotionEvent event) { + switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: { onListTouched(); break; @@ -180,6 +187,11 @@ public class BaseSupportListFragment extends ListFragment implements IBaseFragme } return false; } + + @Override + public boolean onTouchEvent(View view, MotionEvent event) { + return false; + } }; protected void onListTouched() { @@ -189,8 +201,6 @@ public class BaseSupportListFragment extends ListFragment implements IBaseFragme @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - final ListView listView = getListView(); - listView.setOnTouchListener(mInternalOnTouchListener); requestFitSystemWindows(); } @@ -232,8 +242,9 @@ public class BaseSupportListFragment extends ListFragment implements IBaseFragme // ------------------------------------------------------------------ - final FrameLayout lframe = new FrameLayout(context); + final ExtendedFrameLayout lframe = new ExtendedFrameLayout(context); lframe.setId(INTERNAL_LIST_CONTAINER_ID); + lframe.setTouchInterceptor(mInternalOnTouchListener); final TextView tv = new TextView(getActivity()); tv.setTextAppearance(context, ThemeUtils.getTextAppearanceLarge(context)); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUserListsListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUserListsListFragment.java index 26927b16d..e53d7e967 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUserListsListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUserListsListFragment.java @@ -19,9 +19,6 @@ package org.mariotaku.twidere.fragment.support; -import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter; -import static org.mariotaku.twidere.util.Utils.openUserListDetails; - import android.content.ActivityNotFoundException; import android.content.Context; import android.content.SharedPreferences; @@ -48,204 +45,207 @@ import org.mariotaku.twidere.util.MultiSelectManager; import java.util.ArrayList; import java.util.List; +import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter; +import static org.mariotaku.twidere.util.Utils.openUserListDetails; + abstract class BaseUserListsListFragment extends BasePullToRefreshListFragment implements - LoaderCallbacks>, Panes.Left, OnMenuItemClickListener, MenuButtonClickListener { + LoaderCallbacks>, Panes.Left, OnMenuItemClickListener, MenuButtonClickListener { - private ParcelableUserListsAdapter mAdapter; + private ParcelableUserListsAdapter mAdapter; - private SharedPreferences mPreferences; - private ListView mListView; + private SharedPreferences mPreferences; + private ListView mListView; - private long mAccountId, mUserId; - private String mScreenName; - private final ArrayList mData = new ArrayList(); - private ParcelableUserList mSelectedUserList; - private long mCursor = -1; - private boolean mLoadMoreAutomatically; + private long mAccountId, mUserId; + private String mScreenName; + private final ArrayList mData = new ArrayList<>(); + private ParcelableUserList mSelectedUserList; + private long mCursor = -1; + private boolean mLoadMoreAutomatically; - private AsyncTwitterWrapper mTwitterWrapper; - private MultiSelectManager mMultiSelectManager; + private AsyncTwitterWrapper mTwitterWrapper; + private MultiSelectManager mMultiSelectManager; - public long getAccountId() { - return mAccountId; - } + public long getAccountId() { + return mAccountId; + } - public long getCursor() { - return mCursor; - } + public long getCursor() { + return mCursor; + } - public final ArrayList getData() { - return mData; - } + public final ArrayList getData() { + return mData; + } - @Override - public ParcelableUserListsAdapter getListAdapter() { - return mAdapter; - } + @Override + public ParcelableUserListsAdapter getListAdapter() { + return mAdapter; + } - public String getScreenName() { - return mScreenName; - } + public String getScreenName() { + return mScreenName; + } - public long getUserId() { - return mUserId; - } + public long getUserId() { + return mUserId; + } - public void loadMoreUserLists() { - final int count = mAdapter.getCount(); - if (count - 1 > 0) { - final Bundle args = getArguments(); - if (args != null) { - args.putLong(EXTRA_MAX_ID, mAdapter.getItem(count - 1).user_id); - } - if (!getLoaderManager().hasRunningLoaders()) { - getLoaderManager().restartLoader(0, args, this); - } - } - } + public void loadMoreUserLists() { + final int count = mAdapter.getCount(); + if (count - 1 > 0) { + final Bundle args = getArguments(); + if (args != null) { + args.putLong(EXTRA_MAX_ID, mAdapter.getItem(count - 1).user_id); + } + if (!getLoaderManager().hasRunningLoaders()) { + getLoaderManager().restartLoader(0, args, this); + } + } + } - public abstract Loader> newLoaderInstance(long accountId, long userId, String screen_name); + public abstract Loader> newLoaderInstance(long accountId, long userId, String screen_name); - @Override - public void onActivityCreated(final Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - mTwitterWrapper = getTwitterWrapper(); - mMultiSelectManager = getMultiSelectManager(); - mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - final Bundle args = getArguments(); - if (args != null) { - mAccountId = args.getLong(EXTRA_ACCOUNT_ID, -1); - mUserId = args.getLong(EXTRA_USER_ID, -1); - mScreenName = args.getString(EXTRA_SCREEN_NAME); - } - mAdapter = new ParcelableUserListsAdapter(getActivity()); - mListView = getListView(); - mListView.setDivider(null); - mListView.setSelector(android.R.color.transparent); - mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false)); - // final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1); - // if (mAccountId != account_id) { - // mAdapter.clear(); - // mData.clear(); - // } - // mAccountId = account_id; - setListAdapter(mAdapter); - mAdapter.setMenuButtonClickListener(this); - getLoaderManager().initLoader(0, getArguments(), this); - setListShown(false); - setRefreshMode(RefreshMode.NONE); - } + @Override + public void onActivityCreated(final Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mTwitterWrapper = getTwitterWrapper(); + mMultiSelectManager = getMultiSelectManager(); + mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + final Bundle args = getArguments(); + if (args != null) { + mAccountId = args.getLong(EXTRA_ACCOUNT_ID, -1); + mUserId = args.getLong(EXTRA_USER_ID, -1); + mScreenName = args.getString(EXTRA_SCREEN_NAME); + } + mAdapter = new ParcelableUserListsAdapter(getActivity()); + mListView = getListView(); + mListView.setDivider(null); + mListView.setSelector(android.R.color.transparent); + mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false)); + // final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1); + // if (mAccountId != account_id) { + // mAdapter.clear(); + // mData.clear(); + // } + // mAccountId = account_id; + setListAdapter(mAdapter); + mAdapter.setMenuButtonClickListener(this); + getLoaderManager().initLoader(0, getArguments(), this); + setListShown(false); + setRefreshMode(RefreshMode.NONE); + } - @Override - public Loader> onCreateLoader(final int id, final Bundle args) { - setProgressBarIndeterminateVisibility(true); - return newLoaderInstance(mAccountId, mUserId, mScreenName); - } + @Override + public Loader> onCreateLoader(final int id, final Bundle args) { + setProgressBarIndeterminateVisibility(true); + return newLoaderInstance(mAccountId, mUserId, mScreenName); + } - @Override - public final void onListItemClick(final ListView view, final View child, final int position, final long id) { - if (mMultiSelectManager.isActive()) return; - final ParcelableUserList userList = mAdapter.findItem(id); - if (userList == null) return; - openUserListDetails(getActivity(), userList); - } + @Override + public final void onListItemClick(final ListView view, final View child, final int position, final long id) { + if (mMultiSelectManager.isActive()) return; + final int userListPosition = mAdapter.findItemPosition(id); + if (userListPosition < 0) return; + openUserListDetails(getActivity(), mAdapter.getItem(userListPosition)); + } - @Override - public void onLoaderReset(final Loader> loader) { - setProgressBarIndeterminateVisibility(false); - } + @Override + public void onLoaderReset(final Loader> loader) { + setProgressBarIndeterminateVisibility(false); + } - @Override - public void onLoadFinished(final Loader> loader, final List data) { - setProgressBarIndeterminateVisibility(false); - mAdapter.appendData(data); - if (loader instanceof BaseUserListsLoader) { - final long cursor = ((BaseUserListsLoader) loader).getNextCursor(); - if (cursor != -2) { - mCursor = cursor; - } - } - setRefreshComplete(); - setListShown(true); - } + @Override + public void onLoadFinished(final Loader> loader, final List data) { + setProgressBarIndeterminateVisibility(false); + mAdapter.appendData(data); + if (loader instanceof BaseUserListsLoader) { + final long cursor = ((BaseUserListsLoader) loader).getNextCursor(); + if (cursor != -2) { + mCursor = cursor; + } + } + setRefreshComplete(); + setListShown(true); + } - @Override - public void onMenuButtonClick(final View button, final int position, final long id) { - final ParcelableUserList userList = mAdapter.getItem(position - mListView.getHeaderViewsCount()); - if (userList == null) return; - showMenu(button, userList); - } + @Override + public void onMenuButtonClick(final View button, final int position, final long id) { + final ParcelableUserList userList = mAdapter.getItem(position - mListView.getHeaderViewsCount()); + if (userList == null) return; + showMenu(button, userList); + } - @Override - public boolean onMenuItemClick(final MenuItem item) { - if (mSelectedUserList == null) return false; - switch (item.getItemId()) { - case MENU_ADD: { - AddUserListMemberDialogFragment.show(getFragmentManager(), mSelectedUserList.account_id, - mSelectedUserList.id); - break; - } - case MENU_DELETE: { - mTwitterWrapper.destroyUserListAsync(mSelectedUserList.account_id, mSelectedUserList.id); - break; - } - default: { - if (item.getIntent() != null) { - try { - startActivity(item.getIntent()); - } catch (final ActivityNotFoundException e) { - Log.w(LOGTAG, e); - return false; - } - } - break; - } - } - return true; - } + @Override + public boolean onMenuItemClick(final MenuItem item) { + if (mSelectedUserList == null) return false; + switch (item.getItemId()) { + case MENU_ADD: { + AddUserListMemberDialogFragment.show(getFragmentManager(), mSelectedUserList.account_id, + mSelectedUserList.id); + break; + } + case MENU_DELETE: { + mTwitterWrapper.destroyUserListAsync(mSelectedUserList.account_id, mSelectedUserList.id); + break; + } + default: { + if (item.getIntent() != null) { + try { + startActivity(item.getIntent()); + } catch (final ActivityNotFoundException e) { + Log.w(LOGTAG, e); + return false; + } + } + break; + } + } + return true; + } - @Override - public void onRefreshFromEnd() { - if (mLoadMoreAutomatically) return; - loadMoreUserLists(); - } + @Override + public void onRefreshFromEnd() { + if (mLoadMoreAutomatically) return; + loadMoreUserLists(); + } - @Override - public void onRefreshFromStart() { - if (isRefreshing()) return; - getLoaderManager().restartLoader(0, getArguments(), this); - } + @Override + public void onRefreshFromStart() { + if (isRefreshing()) return; + getLoaderManager().restartLoader(0, getArguments(), this); + } - @Override - public void onResume() { - super.onResume(); - mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false); - configBaseCardAdapter(getActivity(), mAdapter); - } + @Override + public void onResume() { + super.onResume(); + mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false); + configBaseCardAdapter(getActivity(), mAdapter); + } - @Override - public void onScrollStateChanged(final AbsListView view, final int scrollState) { - } + @Override + public void onScrollStateChanged(final AbsListView view, final int scrollState) { + } - protected UserListMenuDialogFragment createMenuDialog() { - return new UserListMenuDialogFragment(); - } + protected UserListMenuDialogFragment createMenuDialog() { + return new UserListMenuDialogFragment(); + } - @Override - protected void onReachedBottom() { - if (!mLoadMoreAutomatically) return; - loadMoreUserLists(); - } + @Override + protected void onReachedBottom() { + if (!mLoadMoreAutomatically) return; + loadMoreUserLists(); + } - private void showMenu(final View view, final ParcelableUserList userList) { - mSelectedUserList = userList; - final FragmentActivity activity = getActivity(); - if (activity == null || activity.isFinishing() || view == null || userList == null) return; - final UserListMenuDialogFragment df = createMenuDialog(); - final Bundle args = new Bundle(); - args.putParcelable(EXTRA_USER_LIST, userList); - df.setArguments(args); - df.show(getChildFragmentManager(), "user_list_menu"); - } + private void showMenu(final View view, final ParcelableUserList userList) { + mSelectedUserList = userList; + final FragmentActivity activity = getActivity(); + if (activity == null || activity.isFinishing() || view == null || userList == null) return; + final UserListMenuDialogFragment df = createMenuDialog(); + final Bundle args = new Bundle(); + args.putParcelable(EXTRA_USER_LIST, userList); + df.setArguments(args); + df.show(getChildFragmentManager(), "user_list_menu"); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUsersListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUsersListFragment.java index e87b3bdca..3279b2859 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUsersListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseUsersListFragment.java @@ -19,11 +19,6 @@ package org.mariotaku.twidere.fragment.support; -import static org.mariotaku.twidere.util.Utils.clearListViewChoices; -import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter; -import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds; -import static org.mariotaku.twidere.util.Utils.openUserProfile; - import android.content.ActivityNotFoundException; import android.content.Context; import android.content.SharedPreferences; @@ -51,251 +46,259 @@ import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList; import java.util.Collections; import java.util.List; +import static org.mariotaku.twidere.util.Utils.clearListViewChoices; +import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter; +import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds; +import static org.mariotaku.twidere.util.Utils.openUserProfile; + abstract class BaseUsersListFragment extends BasePullToRefreshListFragment implements - LoaderCallbacks>, OnItemLongClickListener, Panes.Left, OnMenuItemClickListener, - MultiSelectManager.Callback, MenuButtonClickListener { + LoaderCallbacks>, OnItemLongClickListener, Panes.Left, OnMenuItemClickListener, + MultiSelectManager.Callback, MenuButtonClickListener { - private SharedPreferences mPreferences; - private MultiSelectManager mMultiSelectManager; + private SharedPreferences mPreferences; + private MultiSelectManager mMultiSelectManager; - private ParcelableUsersAdapter mAdapter; + private ParcelableUsersAdapter mAdapter; - private boolean mLoadMoreAutomatically; - private ListView mListView; - private long mAccountId; + private boolean mLoadMoreAutomatically; + private ListView mListView; + private long mAccountId; - private final List mData = Collections - .synchronizedList(new NoDuplicatesArrayList()); - private ParcelableUser mSelectedUser; + private final List mData = Collections + .synchronizedList(new NoDuplicatesArrayList()); + private ParcelableUser mSelectedUser; - public long getAccountId() { - return mAccountId; - } + public long getAccountId() { + return mAccountId; + } - public final List getData() { - return mData; - } + public final List getData() { + return mData; + } - @Override - public ParcelableUsersAdapter getListAdapter() { - return mAdapter; - } + @Override + public ParcelableUsersAdapter getListAdapter() { + return mAdapter; + } - public SharedPreferences getSharedPreferences() { - return mPreferences; - } + public SharedPreferences getSharedPreferences() { + return mPreferences; + } - public void loadMoreUsers() { - if (isRefreshing()) return; - final int count = mAdapter.getCount(); - if (count - 1 > 0) { - final Bundle args = getArguments(); - if (args != null) { - args.putLong(EXTRA_MAX_ID, mAdapter.getItem(count - 1).id); - } - if (!getLoaderManager().hasRunningLoaders()) { - getLoaderManager().restartLoader(0, args, this); - } - } - } + public void loadMoreUsers() { + if (isRefreshing()) return; + final int count = mAdapter.getCount(); + if (count - 1 > 0) { + final Bundle args = getArguments(); + if (args != null) { + args.putLong(EXTRA_MAX_ID, mAdapter.getItem(count - 1).id); + } + if (!getLoaderManager().hasRunningLoaders()) { + getLoaderManager().restartLoader(0, args, this); + } + } + } - @Override - public void onActivityCreated(final Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - mAdapter = new ParcelableUsersAdapter(getActivity()); - mAdapter.setMenuButtonClickListener(this); - mMultiSelectManager = getMultiSelectManager(); - mListView = getListView(); - mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false)); - final Bundle args = getArguments() != null ? getArguments() : new Bundle(); - final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1); - if (mAccountId != accountId) { - mAdapter.clear(); - mData.clear(); - } - mAccountId = accountId; - if (!mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false)) { - mListView.setDivider(null); - } - mListView.setSelector(android.R.color.transparent); - mListView.setOnItemLongClickListener(this); - setListAdapter(mAdapter); - getLoaderManager().initLoader(0, getArguments(), this); - setListShown(false); - } + @Override + public void onActivityCreated(final Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + mAdapter = new ParcelableUsersAdapter(getActivity()); + mAdapter.setMenuButtonClickListener(this); + mMultiSelectManager = getMultiSelectManager(); + mListView = getListView(); + mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false)); + final Bundle args = getArguments() != null ? getArguments() : new Bundle(); + final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1); + if (mAccountId != accountId) { + mAdapter.clear(); + mData.clear(); + } + mAccountId = accountId; + if (!mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false)) { + mListView.setDivider(null); + } + mListView.setSelector(android.R.color.transparent); + mListView.setOnItemLongClickListener(this); + setListAdapter(mAdapter); + getLoaderManager().initLoader(0, getArguments(), this); + setListShown(false); + } - @Override - public Loader> onCreateLoader(final int id, final Bundle args) { - setProgressBarIndeterminateVisibility(true); - final Loader> loader = newLoaderInstance(getActivity(), args); - return loader != null ? loader : new DummyParcelableUsersLoader(getActivity()); - } + @Override + public Loader> onCreateLoader(final int id, final Bundle args) { + setProgressBarIndeterminateVisibility(true); + final Loader> loader = newLoaderInstance(getActivity(), args); + return loader != null ? loader : new DummyParcelableUsersLoader(getActivity()); + } - @Override - public boolean onItemLongClick(final AdapterView parent, final View view, final int position, final long id) { - final ParcelableUsersAdapter adapter = getListAdapter(); - final ParcelableUser user = adapter.findItem(id); - if (user == null) return false; - setItemSelected(user, position, !mMultiSelectManager.isSelected(user)); - return true; - } + @Override + public boolean onItemLongClick(final AdapterView parent, final View view, final int position, final long id) { + final ParcelableUsersAdapter adapter = getListAdapter(); + final int userPosition = adapter.findItemPosition(id); + if (userPosition < 0) return false; + final ParcelableUser user = adapter.getItem(userPosition); + setItemSelected(user, position, !mMultiSelectManager.isSelected(user)); + return true; + } - @Override - public void onItemsCleared() { - clearListViewChoices(mListView); - } + @Override + public void onItemsCleared() { + clearListViewChoices(mListView); + } - @Override - public void onItemSelected(final Object item) { - mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - } + @Override + public void onItemSelected(final Object item) { + mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + } - @Override - public void onItemUnselected(final Object item) { - } + @Override + public void onItemUnselected(final Object item) { + } - @Override - public void onListItemClick(final ListView l, final View v, final int position, final long id) { - final ParcelableUser user = mAdapter.findItem(id); - if (user == null) return; - if (mMultiSelectManager.isActive()) { - setItemSelected(user, position, !mMultiSelectManager.isSelected(user)); - return; - } - openUserProfile(getActivity(), user); - } + @Override + public void onListItemClick(final ListView l, final View v, final int position, final long id) { + final ParcelableUsersAdapter adapter = getListAdapter(); + final int userPosition = adapter.findItemPosition(id); + if (userPosition < 0) return; + final ParcelableUser user = adapter.getItem(userPosition); + if (mMultiSelectManager.isActive()) { + setItemSelected(user, position, !mMultiSelectManager.isSelected(user)); + return; + } + openUserProfile(getActivity(), user); + } - @Override - public void onLoaderReset(final Loader> loader) { - setProgressBarIndeterminateVisibility(false); - } + @Override + public void onLoaderReset(final Loader> loader) { + setProgressBarIndeterminateVisibility(false); + } - @Override - public void onLoadFinished(final Loader> loader, final List data) { - setProgressBarIndeterminateVisibility(false); - mAdapter.setData(data); - mAdapter.setShowAccountColor(shouldShowAccountColor()); - setRefreshComplete(); - setListShown(true); - } + @Override + public void onLoadFinished(final Loader> loader, final List data) { + setProgressBarIndeterminateVisibility(false); + mAdapter.setData(data); + mAdapter.setShowAccountColor(shouldShowAccountColor()); + setRefreshComplete(); + setListShown(true); + } - @Override - public void onMenuButtonClick(final View button, final int position, final long id) { - final ParcelableUser user = mAdapter.getItem(position - mListView.getHeaderViewsCount()); - if (user == null) return; - showMenu(button, user); - } + @Override + public void onMenuButtonClick(final View button, final int position, final long id) { + final ParcelableUser user = mAdapter.getItem(position - mListView.getHeaderViewsCount()); + if (user == null) return; + showMenu(button, user); + } - @Override - public boolean onMenuItemClick(final MenuItem item) { - if (mSelectedUser == null) return false; - switch (item.getItemId()) { - default: { - if (item.getIntent() != null) { - try { - startActivity(item.getIntent()); - } catch (final ActivityNotFoundException e) { - Log.w(LOGTAG, e); - return false; - } - } - break; - } - } - return true; - } + @Override + public boolean onMenuItemClick(final MenuItem item) { + if (mSelectedUser == null) return false; + switch (item.getItemId()) { + default: { + if (item.getIntent() != null) { + try { + startActivity(item.getIntent()); + } catch (final ActivityNotFoundException e) { + Log.w(LOGTAG, e); + return false; + } + } + break; + } + } + return true; + } - @Override - public void onReachedBottom() { - if (!mLoadMoreAutomatically) return; - loadMoreUsers(); - } + @Override + public void onReachedBottom() { + if (!mLoadMoreAutomatically) return; + loadMoreUsers(); + } - @Override - public void onRefreshFromEnd() { - if (mLoadMoreAutomatically) return; - loadMoreUsers(); - } + @Override + public void onRefreshFromEnd() { + if (mLoadMoreAutomatically) return; + loadMoreUsers(); + } - @Override - public void onRefreshFromStart() { - if (isRefreshing()) return; - getLoaderManager().restartLoader(0, getArguments(), this); - } + @Override + public void onRefreshFromStart() { + if (isRefreshing()) return; + getLoaderManager().restartLoader(0, getArguments(), this); + } - @Override - public void onResume() { - super.onResume(); - mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false); - configBaseCardAdapter(getActivity(), mAdapter); - } + @Override + public void onResume() { + super.onResume(); + mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false); + configBaseCardAdapter(getActivity(), mAdapter); + } - @Override - public void onStart() { - super.onStart(); - mMultiSelectManager.registerCallback(this); - final int choiceMode = mListView.getChoiceMode(); - if (mMultiSelectManager.isActive()) { - if (choiceMode != ListView.CHOICE_MODE_MULTIPLE) { - mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - } - } else { - if (choiceMode != ListView.CHOICE_MODE_NONE) { - Utils.clearListViewChoices(mListView); - } - } - } + @Override + public void onStart() { + super.onStart(); + mMultiSelectManager.registerCallback(this); + final int choiceMode = mListView.getChoiceMode(); + if (mMultiSelectManager.isActive()) { + if (choiceMode != ListView.CHOICE_MODE_MULTIPLE) { + mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + } + } else { + if (choiceMode != ListView.CHOICE_MODE_NONE) { + Utils.clearListViewChoices(mListView); + } + } + } - @Override - public void onStop() { - mMultiSelectManager.unregisterCallback(this); - super.onStop(); - } + @Override + public void onStop() { + mMultiSelectManager.unregisterCallback(this); + super.onStop(); + } - protected UserMenuDialogFragment createMenuDialog() { - return new UserMenuDialogFragment(); - } + protected UserMenuDialogFragment createMenuDialog() { + return new UserMenuDialogFragment(); + } - protected ParcelableUser getSelectedUser() { - return mSelectedUser; - } + protected ParcelableUser getSelectedUser() { + return mSelectedUser; + } - protected int getUserMenuResource() { - return 0; - } + protected int getUserMenuResource() { + return 0; + } - protected abstract Loader> newLoaderInstance(Context context, Bundle args); + protected abstract Loader> newLoaderInstance(Context context, Bundle args); - protected final void removeUsers(final long... user_ids) { - if (user_ids == null || user_ids.length == 0) return; - for (final long user_id : user_ids) { - mData.remove(mAdapter.findItem(user_id)); - } - mAdapter.setData(mData, true); - } + protected final void removeUsers(final long... userIds) { + if (userIds == null || userIds.length == 0) return; + for (final long userId : userIds) { + mData.remove(mAdapter.findItemPosition(userId)); + } + mAdapter.setData(mData, true); + } - protected void setItemSelected(final ParcelableUser user, final int position, final boolean selected) { - if (selected) { - mMultiSelectManager.selectItem(user); - } else { - mMultiSelectManager.unselectItem(user); - } - mListView.setItemChecked(position, selected); - } + protected void setItemSelected(final ParcelableUser user, final int position, final boolean selected) { + if (selected) { + mMultiSelectManager.selectItem(user); + } else { + mMultiSelectManager.unselectItem(user); + } + mListView.setItemChecked(position, selected); + } - protected boolean shouldShowAccountColor() { - return getActivatedAccountIds(getActivity()).length > 1; - } + protected boolean shouldShowAccountColor() { + return getActivatedAccountIds(getActivity()).length > 1; + } - private void showMenu(final View view, final ParcelableUser user) { - mSelectedUser = user; - final FragmentActivity activity = getActivity(); - if (activity == null || activity.isFinishing() || view == null || user == null) return; - final UserMenuDialogFragment df = createMenuDialog(); - final Bundle args = new Bundle(); - args.putParcelable(EXTRA_USER, user); - df.setArguments(args); - df.show(getChildFragmentManager(), "user_menu"); - } + private void showMenu(final View view, final ParcelableUser user) { + mSelectedUser = user; + final FragmentActivity activity = getActivity(); + if (activity == null || activity.isFinishing() || view == null || user == null) return; + final UserMenuDialogFragment df = createMenuDialog(); + final Bundle args = new Bundle(); + args.putParcelable(EXTRA_USER, user); + df.setArguments(args); + df.show(getChildFragmentManager(), "user_menu"); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesListFragment.java index 838981965..df6decd58 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesListFragment.java @@ -22,6 +22,7 @@ package org.mariotaku.twidere.fragment.support; import android.app.Activity; import android.content.ContentResolver; import android.content.Context; +import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -69,14 +70,16 @@ public abstract class CursorStatusesListFragment extends BaseStatusesListFragmen @Override public Loader onCreateLoader(final int id, final Bundle args) { final Context context = getActivity(); + final SharedPreferences preferences = getSharedPreferences(); + final boolean sortById = preferences.getBoolean(KEY_SORT_TIMELINE_BY_ID, false); final Uri uri = getContentUri(); final String table = getTableNameByUri(uri); - final String sortOrder = Statuses.DEFAULT_SORT_ORDER; - final long account_id = getAccountId(); - final long[] accountIds = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(context); - final boolean no_account_selected = accountIds.length == 0; - setEmptyText(no_account_selected ? getString(R.string.no_account_selected) : null); - if (!no_account_selected) { + final String sortOrder = sortById ? Statuses.SORT_ORDER_STATUS_ID_DESC : Statuses.SORT_ORDER_TIMESTAMP_DESC; + final long accountId = getAccountId(); + final long[] accountIds = accountId > 0 ? new long[]{accountId} : getActivatedAccountIds(context); + final boolean noAccountSelected = accountIds.length == 0; + setEmptyText(noAccountSelected ? getString(R.string.no_account_selected) : null); + if (!noAccountSelected) { getListView().setEmptyView(null); } final Where accountWhere = Where.in(new Column(Statuses.ACCOUNT_ID), new RawItemArray(accountIds)); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListsListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListsListFragment.java index b36adc009..dcdddeaed 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListsListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListsListFragment.java @@ -116,7 +116,7 @@ public class UserListsListFragment extends BaseUserListsListFragment { final ParcelableUserListsAdapter adapter = getListAdapter(); final int listsIdx = adapter.findItemPosition(id); if (listsIdx >= 0) { - adapter.remove(listsIdx); + adapter.removeAt(listsIdx); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/Account.java b/twidere/src/main/java/org/mariotaku/twidere/model/Account.java index d411fe6b3..9aed71032 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/Account.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/Account.java @@ -24,6 +24,7 @@ import android.database.Cursor; import android.graphics.Color; import android.os.Parcel; import android.os.Parcelable; +import android.support.annotation.NonNull; import org.mariotaku.querybuilder.Columns.Column; import org.mariotaku.querybuilder.RawItemArray; @@ -180,27 +181,27 @@ public class Account implements Parcelable { public static List getAccountsList(final Context context, final boolean activatedOnly, final boolean officialKeyOnly) { if (context == null) return Collections.emptyList(); - final ArrayList accounts = new ArrayList(); - final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI, - Accounts.COLUMNS_NO_CREDENTIALS, activatedOnly ? Accounts.IS_ACTIVATED + " = 1" : null, null, null); - if (cur != null) { - final Indices indices = new Indices(cur); - cur.moveToFirst(); - while (!cur.isAfterLast()) { - if (!officialKeyOnly) { + final ArrayList accounts = new ArrayList<>(); + final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), + Accounts.CONTENT_URI, Accounts.COLUMNS_NO_CREDENTIALS, + activatedOnly ? Accounts.IS_ACTIVATED + " = 1" : null, null, Accounts.SORT_POSITION); + if (cur == null) return accounts; + final Indices indices = new Indices(cur); + cur.moveToFirst(); + while (!cur.isAfterLast()) { + if (!officialKeyOnly) { + accounts.add(new Account(cur, indices)); + } else { + final String consumerKey = cur.getString(indices.consumer_key); + final String consumerSecret = cur.getString(indices.consumer_secret); + if (shouldForceUsingPrivateAPIs(context) + || isOfficialConsumerKeySecret(context, consumerKey, consumerSecret)) { accounts.add(new Account(cur, indices)); - } else { - final String consumerKey = cur.getString(indices.consumer_key); - final String consumerSecret = cur.getString(indices.consumer_secret); - if (shouldForceUsingPrivateAPIs(context) - || isOfficialConsumerKeySecret(context, consumerKey, consumerSecret)) { - accounts.add(new Account(cur, indices)); - } } - cur.moveToNext(); } - cur.close(); + cur.moveToNext(); } + cur.close(); return accounts; } @@ -253,7 +254,7 @@ public class Account implements Parcelable { + ", api_url_format=" + api_url_format + ", same_oauth_signing_url=" + same_oauth_signing_url + "}"; } - public static final boolean isOfficialCredentials(final Context context, final AccountWithCredentials account) { + public static boolean isOfficialCredentials(final Context context, final AccountWithCredentials account) { if (account == null) return false; final boolean isOAuth = account.auth_type == Accounts.AUTH_TYPE_OAUTH || account.auth_type == Accounts.AUTH_TYPE_XAUTH; @@ -268,7 +269,7 @@ public class Account implements Parcelable { auth_type, consumer_key, consumer_secret, basic_auth_username, basic_auth_password, oauth_token, oauth_token_secret, api_url_format, same_oauth_signing_url, no_version_suffix; - public Indices(final Cursor cursor) { + public Indices(@NonNull final Cursor cursor) { screen_name = cursor.getColumnIndex(Accounts.SCREEN_NAME); name = cursor.getColumnIndex(Accounts.NAME); account_id = cursor.getColumnIndex(Accounts.ACCOUNT_ID); diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java index d207c224c..c8feab2fb 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -1259,20 +1259,18 @@ public final class Utils implements Constants, TwitterConstants { } } - public static int[] getAccountColors(final Context context, final long[] account_ids) { - if (context == null || account_ids == null) return new int[0]; - final String[] cols = new String[]{Accounts.COLOR}; - final String where = Where.in(new Column(Accounts.ACCOUNT_ID), new RawItemArray(account_ids)).getSQL(); + public static int[] getAccountColors(final Context context, final long[] accountIds) { + if (context == null || accountIds == null) return new int[0]; + final String[] cols = new String[]{Accounts.ACCOUNT_ID, Accounts.COLOR}; + final String where = Where.in(new Column(Accounts.ACCOUNT_ID), new RawItemArray(accountIds)).getSQL(); final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI, cols, where, null, null); if (cur == null) return new int[0]; try { - cur.moveToFirst(); final int[] colors = new int[cur.getCount()]; - int i = 0; - while (!cur.isAfterLast()) { - colors[i++] = cur.getInt(0); - cur.moveToNext(); + for (int i = 0, j = cur.getCount(); i < j; i++) { + cur.moveToPosition(i); + colors[ArrayUtils.indexOf(accountIds, cur.getLong(0))] = cur.getInt(1); } return colors; } finally { @@ -1653,10 +1651,10 @@ public final class Utils implements Constants, TwitterConstants { final String screen_name, final boolean ignore_cache) { if (context == null) return null; final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - final boolean name_first = prefs.getBoolean(KEY_NAME_FIRST, true); - final boolean nickname_only = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) + final boolean nameFirst = prefs.getBoolean(KEY_NAME_FIRST, true); + final boolean nicknameOnly = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) .getBoolean(KEY_NICKNAME_ONLY, false); - return getDisplayName(context, user_id, name, screen_name, name_first, nickname_only, ignore_cache); + return getDisplayName(context, user_id, name, screen_name, nameFirst, nicknameOnly, ignore_cache); } public static String getDisplayName(final Context context, final long user_id, final String name, diff --git a/twidere/src/main/res/layout/action_item_compose_account.xml b/twidere/src/main/res/layout/action_item_compose_account.xml index 4f9e23a06..8431885cd 100644 --- a/twidere/src/main/res/layout/action_item_compose_account.xml +++ b/twidere/src/main/res/layout/action_item_compose_account.xml @@ -6,4 +6,13 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="match_parent" - app:ignorePadding="true"/> \ No newline at end of file + app:ignorePadding="true"> + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/activity_compose.xml b/twidere/src/main/res/layout/activity_compose.xml index 47dcdcfe4..5a38dfdd5 100644 --- a/twidere/src/main/res/layout/activity_compose.xml +++ b/twidere/src/main/res/layout/activity_compose.xml @@ -1,65 +1,64 @@ + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:minHeight="@dimen/compose_min_height" + android:minWidth="@dimen/compose_min_width" + android:orientation="vertical"> - + android:layout="@layout/activity_compose_actionbar"/> - + - + - + - + - - - + + + - - + android:layout="@layout/activity_compose_bottombar"/> + \ No newline at end of file diff --git a/twidere/src/main/res/layout/tab_item_home.xml b/twidere/src/main/res/layout/tab_item_home.xml index d42d18892..00449e82c 100644 --- a/twidere/src/main/res/layout/tab_item_home.xml +++ b/twidere/src/main/res/layout/tab_item_home.xml @@ -25,14 +25,18 @@ + android:layout_marginTop="@dimen/element_spacing_minus_small" + android:background="@drawable/bg_unread_indicator" + android:ellipsize="none" + android:gravity="center" + android:padding="@dimen/element_spacing_xsmall" + android:singleLine="true" + app:minTextSize="0.5sp" + app:sizeToFit="true"/> \ No newline at end of file diff --git a/twidere/src/main/res/values/strings.xml b/twidere/src/main/res/values/strings.xml index c8b5b8841..fa3541374 100644 --- a/twidere/src/main/res/values/strings.xml +++ b/twidere/src/main/res/values/strings.xml @@ -660,5 +660,6 @@ unmuting Mute %s? You will no longer see tweets from this user while keep following this user. Remove from filter + Sort timeline by id \ No newline at end of file diff --git a/twidere/src/main/res/xml/settings_content.xml b/twidere/src/main/res/xml/settings_content.xml index 586ba2c47..d56af5a26 100644 --- a/twidere/src/main/res/xml/settings_content.xml +++ b/twidere/src/main/res/xml/settings_content.xml @@ -1,118 +1,122 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + android:key="settings_content" + android:title="@string/content_and_storage"> - - + + - + - + - - - - + + + + - + - + - + - + - + - + - - + + + - + - - - - - - + + + + + + \ No newline at end of file