From ef2e93da4e21ee4083d994eb63ba1a67e37793b2 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 19 Nov 2014 13:06:09 +0800 Subject: [PATCH] implementing new tweets list --- .../twidere/activity/SettingsActivity.java | 29 +- .../support/BrowserSignInActivity.java | 6 +- .../activity/support/ComposeActivity.java | 2 +- .../adapter/CursorStatusesAdapter.java | 4 +- .../adapter/ParcelableStatusesAdapter.java | 4 +- .../decorator/DividerItemDecoration.java | 108 ++++++ .../adapter/iface/IStatusesAdapter.java | 66 +--- .../adapter/iface/IStatusesListAdapter.java | 67 ++++ .../support/BaseStatusesListFragment.java | 11 +- .../BaseStatusesStaggeredGridFragment.java | 10 +- .../ParcelableStatusesListFragment.java | 10 +- .../support/RetweetsOfMeFragment.java | 4 +- .../support/SearchStatusesFragment.java | 6 +- .../fragment/support/StatusFragment.java | 18 +- .../support/UserFavoritesFragment.java | 4 +- .../support/UserListTimelineFragment.java | 4 +- .../support/UserTimelineFragment.java | 4 +- .../support/UserTimelineFragment2.java | 339 ++++++++++++++++++ .../preference/AccountsListPreference.java | 22 +- .../preference/ThemeBackgroundPreference.java | 7 + .../twidere/util/ImageLoaderWrapper.java | 23 +- .../twidere/util/MessagesManager.java | 237 ++++++------ .../org/mariotaku/twidere/util/Utils.java | 55 ++- .../util/imageloader/OvalBitmapDisplayer.java | 124 +++++++ .../twidere/view/IconActionButton.java | 49 +++ .../twidere/view/iface/IForegroundView.java | 8 +- .../src/main/java/twitter4j/TwitterImpl.java | 2 + .../main/res/layout/card_item_list_status.xml | 179 +++++++++ .../layout/card_item_list_status_compat.xml | 173 +++++++++ .../res/layout/card_item_load_indicator.xml | 14 + twidere/src/main/res/values-v21/styles.xml | 11 + twidere/src/main/res/values/attrs.xml | 5 + twidere/src/main/res/values/dimens.xml | 2 + twidere/src/main/res/values/styles.xml | 7 + twidere/src/main/res/values/themes.xml | 8 + twidere/src/main/res/xml/settings_storage.xml | 56 +-- 36 files changed, 1375 insertions(+), 303 deletions(-) create mode 100644 twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/DividerItemDecoration.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesListAdapter.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment2.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/util/imageloader/OvalBitmapDisplayer.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/view/IconActionButton.java create mode 100644 twidere/src/main/res/layout/card_item_list_status.xml create mode 100644 twidere/src/main/res/layout/card_item_list_status_compat.xml create mode 100644 twidere/src/main/res/layout/card_item_load_indicator.xml create mode 100644 twidere/src/main/res/values-v21/styles.xml diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java index 4f833725f..bab5b3400 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java @@ -59,10 +59,12 @@ public class SettingsActivity extends BasePreferenceActivity { private HeaderAdapter mAdapter; - private int mCurrentThemeColor, mCurrentThemeBackgroundAlpha; + private int mCurrentThemeColor, mThemeBackgroundAlpha; private boolean mCompactCards, mPlainListStyle; - private String mCurrentThemeFontFamily; + private String mTheme; + private String mThemeFontFamily; + private String mThemeBackground; @Override public void finish() { @@ -150,8 +152,8 @@ public class SettingsActivity extends BasePreferenceActivity { } @Override - public void switchToHeader(final Header header) { - if (header == null || header.fragment == null && header.intent == null) return; + public void switchToHeader(@NonNull final Header header) { + if (header.fragment == null && header.intent == null) return; super.switchToHeader(header); } @@ -178,9 +180,11 @@ public class SettingsActivity extends BasePreferenceActivity { mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE); mCompactCards = mPreferences.getBoolean(KEY_COMPACT_CARDS, false); mPlainListStyle = mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false); + mTheme = mPreferences.getString(KEY_THEME, DEFAULT_THEME); + mThemeBackground = mPreferences.getString(KEY_THEME_BACKGROUND, DEFAULT_THEME_BACKGROUND); + mThemeBackgroundAlpha = mPreferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA); + mThemeFontFamily = mPreferences.getString(KEY_THEME_FONT_FAMILY, DEFAULT_THEME_FONT_FAMILY); mCurrentThemeColor = ThemeUtils.getUserAccentColor(this); - mCurrentThemeFontFamily = getThemeFontFamily(); - mCurrentThemeBackgroundAlpha = getThemeBackgroundAlpha(); super.onCreate(savedInstanceState); setIntent(getIntent().addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)); final ActionBar actionBar = getActionBar(); @@ -193,12 +197,13 @@ public class SettingsActivity extends BasePreferenceActivity { } private boolean shouldNotifyThemeChange() { - return mCompactCards != mPreferences.getBoolean(KEY_COMPACT_CARDS, false) - || mPlainListStyle != mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false) - || getThemeResourceId() != getCurrentThemeResourceId() - || ThemeUtils.getUserAccentColor(this) != mCurrentThemeColor - || !CompareUtils.objectEquals(getThemeFontFamily(), mCurrentThemeFontFamily) - || getThemeBackgroundAlpha() != mCurrentThemeBackgroundAlpha; + return !CompareUtils.objectEquals(mTheme, mPreferences.getString(KEY_THEME, DEFAULT_THEME)) + || !CompareUtils.objectEquals(mThemeFontFamily, mPreferences.getString(KEY_THEME_FONT_FAMILY, DEFAULT_THEME_FONT_FAMILY)) + || !CompareUtils.objectEquals(mThemeBackground, mPreferences.getString(KEY_THEME_BACKGROUND, DEFAULT_THEME_BACKGROUND)) + || mCurrentThemeColor != ThemeUtils.getUserAccentColor(this) + || mThemeBackgroundAlpha != mPreferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA) + || mCompactCards != mPreferences.getBoolean(KEY_COMPACT_CARDS, false) + || mPlainListStyle != mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false); } private static class HeaderAdapter extends ArrayAdapter
{ diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java index 84285d418..52d8e84ce 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java @@ -274,8 +274,10 @@ public class BrowserSignInActivity extends BaseSupportDialogActivity implements mActivity.setLoadProgressShown(false); mActivity.setRequestToken(data); if (data == null) { - Toast.makeText(mActivity, R.string.error_occurred, Toast.LENGTH_SHORT).show(); - mActivity.finish(); + if (!mActivity.isFinishing()) { + Toast.makeText(mActivity, R.string.error_occurred, Toast.LENGTH_SHORT).show(); + mActivity.finish(); + } return; } mActivity.loadUrl(data.getAuthorizationURL()); 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 c5e9d625f..d480553ad 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 @@ -1482,7 +1482,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa final View view = super.getView(position, convertView, parent); final ParcelableMediaUpdate media = getItem(position); final ImageView image = (ImageView) view.findViewById(R.id.image); - mImageLoader.displayPreviewImage(image, media.uri); + mImageLoader.displayPreviewImage(media.uri, image); return view; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java index 0cd8f6876..3a328631f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java @@ -32,7 +32,7 @@ import android.view.ViewGroup; import android.widget.ImageView.ScaleType; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.model.ParcelableMedia; import org.mariotaku.twidere.model.ParcelableStatus; @@ -59,7 +59,7 @@ import static org.mariotaku.twidere.util.Utils.isFiltered; import static org.mariotaku.twidere.util.Utils.openImage; import static org.mariotaku.twidere.util.Utils.openUserProfile; -public class CursorStatusesAdapter extends BaseCursorAdapter implements IStatusesAdapter, OnClickListener, +public class CursorStatusesAdapter extends BaseCursorAdapter implements IStatusesListAdapter, OnClickListener, OnOverflowIconClickListener { public static final String[] CURSOR_COLS = Statuses.COLUMNS; diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableStatusesAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableStatusesAdapter.java index 53e41ffe5..53b291e09 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableStatusesAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableStatusesAdapter.java @@ -31,7 +31,7 @@ import android.view.ViewGroup; import android.widget.ImageView.ScaleType; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableUserMention; @@ -58,7 +58,7 @@ import static org.mariotaku.twidere.util.Utils.openImage; import static org.mariotaku.twidere.util.Utils.openUserProfile; public class ParcelableStatusesAdapter extends BaseArrayAdapter implements - IStatusesAdapter>, OnClickListener, OnOverflowIconClickListener { + IStatusesListAdapter>, OnClickListener, OnOverflowIconClickListener { private final Context mContext; private final MultiSelectManager mMultiSelectManager; diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/DividerItemDecoration.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/DividerItemDecoration.java new file mode 100644 index 000000000..818c9c0dd --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/DividerItemDecoration.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2014 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.decorator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.v4.view.ViewCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +public class DividerItemDecoration extends RecyclerView.ItemDecoration { + + private static final int[] ATTRS = new int[]{ + android.R.attr.listDivider + }; + + public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; + + public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; + + private Drawable mDivider; + + private int mOrientation; + + public DividerItemDecoration(Context context, int orientation) { + final TypedArray a = context.obtainStyledAttributes(ATTRS); + mDivider = a.getDrawable(0); + a.recycle(); + setOrientation(orientation); + } + + public void setOrientation(int orientation) { + if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { + throw new IllegalArgumentException("invalid orientation"); + } + mOrientation = orientation; + } + + @Override + public void onDraw(Canvas c, RecyclerView parent) { + if (mOrientation == VERTICAL_LIST) { + drawVertical(c, parent); + } else { + drawHorizontal(c, parent); + } + } + + public void drawVertical(Canvas c, RecyclerView parent) { + final int left = parent.getPaddingLeft(); + final int right = parent.getWidth() - parent.getPaddingRight(); + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child + .getLayoutParams(); + final int top = child.getBottom() + params.bottomMargin + + Math.round(ViewCompat.getTranslationY(child)); + final int bottom = top + mDivider.getIntrinsicHeight(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + public void drawHorizontal(Canvas c, RecyclerView parent) { + final int top = parent.getPaddingTop(); + final int bottom = parent.getHeight() - parent.getPaddingBottom(); + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child + .getLayoutParams(); + final int left = child.getRight() + params.rightMargin + + Math.round(ViewCompat.getTranslationX(child)); + final int right = left + mDivider.getIntrinsicHeight(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + @Override + public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { + if (mOrientation == VERTICAL_LIST) { + outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); + } else { + outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); + } + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesAdapter.java index 8422b6f25..95896ca2a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesAdapter.java @@ -1,67 +1,11 @@ -/* - * 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 . - */ - package org.mariotaku.twidere.adapter.iface; import org.mariotaku.twidere.model.ParcelableStatus; -public interface IStatusesAdapter extends IBaseCardAdapter { - - public int findPositionByStatusId(final long statusId); - - public long getAccountId(final int position); - - public int getActualCount(); - - public ParcelableStatus getLastStatus(); - - public long getLastStatusId(); - - public ParcelableStatus getStatus(int position); - - public long getStatusId(final int position); - - public boolean isLastItemFiltered(); - - public void setCardHighlightOption(String option); - - public void setData(Data data); - - public void setDisplayImagePreview(boolean display); - - public void setDisplaySensitiveContents(boolean display); - - public void setFavoritesHightlightDisabled(boolean disable); - - public void setFiltersEnabled(boolean enabled); - - public void setGapDisallowed(boolean disallowed); - - public void setHighlightKeyword(String... keywords); - - public void setIgnoredFilterFields(final boolean user, final boolean textPlain, final boolean textHtml, - final boolean source, final boolean retweetedById); - - public void setImagePreviewScaleType(String scaleType); - - public void setIndicateMyStatusDisabled(boolean disable); - - public void setMentionsHightlightDisabled(boolean disable); +/** + * Created by mariotaku on 14/11/18. + */ +public interface IStatusesAdapter { + public ParcelableStatus getStatus(int position); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesListAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesListAdapter.java new file mode 100644 index 000000000..c8d6d9212 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IStatusesListAdapter.java @@ -0,0 +1,67 @@ +/* + * 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 . + */ + +package org.mariotaku.twidere.adapter.iface; + +import org.mariotaku.twidere.model.ParcelableStatus; + +public interface IStatusesListAdapter extends IBaseCardAdapter, IStatusesAdapter { + + public int findPositionByStatusId(final long statusId); + + public long getAccountId(final int position); + + public int getActualCount(); + + public ParcelableStatus getLastStatus(); + + public long getLastStatusId(); + + public ParcelableStatus getStatus(int position); + + public long getStatusId(final int position); + + public boolean isLastItemFiltered(); + + public void setCardHighlightOption(String option); + + public void setData(Data data); + + public void setDisplayImagePreview(boolean display); + + public void setDisplaySensitiveContents(boolean display); + + public void setFavoritesHightlightDisabled(boolean disable); + + public void setFiltersEnabled(boolean enabled); + + public void setGapDisallowed(boolean disallowed); + + public void setHighlightKeyword(String... keywords); + + public void setIgnoredFilterFields(final boolean user, final boolean textPlain, final boolean textHtml, + final boolean source, final boolean retweetedById); + + public void setImagePreviewScaleType(String scaleType); + + public void setIndicateMyStatusDisabled(boolean disable); + + public void setMentionsHightlightDisabled(boolean disable); + +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesListFragment.java index ef2697a10..6fb67f034 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesListFragment.java @@ -38,9 +38,8 @@ import android.widget.ImageView.ScaleType; import android.widget.ListView; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.activity.MainActivity; import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter.MenuButtonClickListener; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.model.Account; import org.mariotaku.twidere.model.Account.AccountWithCredentials; import org.mariotaku.twidere.model.Panes; @@ -79,7 +78,7 @@ abstract class BaseStatusesListFragment extends BasePullToRefreshListFragm private SharedPreferences mPreferences; private ListView mListView; - private IStatusesAdapter mAdapter; + private IStatusesListAdapter mAdapter; private Data mData; private ParcelableStatus mSelectedStatus; @@ -108,7 +107,7 @@ abstract class BaseStatusesListFragment extends BasePullToRefreshListFragm } @Override - public IStatusesAdapter getListAdapter() { + public IStatusesListAdapter getListAdapter() { return mAdapter; } @@ -483,7 +482,7 @@ abstract class BaseStatusesListFragment extends BasePullToRefreshListFragm protected abstract void loadMoreStatuses(); - protected abstract IStatusesAdapter newAdapterInstance(boolean compact, boolean plain); + protected abstract IStatusesListAdapter newAdapterInstance(boolean compact, boolean plain); @Override protected void onReachedBottom() { @@ -571,7 +570,7 @@ abstract class BaseStatusesListFragment extends BasePullToRefreshListFragm static class RemoveUnreadCountsTask extends AsyncTask { private final List read_positions; - private final IStatusesAdapter adapter; + private final IStatusesListAdapter adapter; private final BaseStatusesListFragment fragment; RemoveUnreadCountsTask(final List read_positions, final BaseStatusesListFragment fragment) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesStaggeredGridFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesStaggeredGridFragment.java index 60438d9a2..4a0ac0d84 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesStaggeredGridFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/BaseStatusesStaggeredGridFragment.java @@ -50,7 +50,7 @@ import com.etsy.android.grid.StaggeredGridView; import org.mariotaku.menucomponent.widget.PopupMenu; import org.mariotaku.twidere.R; import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter.MenuButtonClickListener; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.model.Panes; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.task.AsyncTask; @@ -79,7 +79,7 @@ abstract class BaseStatusesStaggeredGridFragment extends BasePullToRefresh private SharedPreferences mPreferences; private StaggeredGridView mListView; - private IStatusesAdapter mAdapter; + private IStatusesListAdapter mAdapter; private PopupMenu mPopupMenu; private Data mData; @@ -109,7 +109,7 @@ abstract class BaseStatusesStaggeredGridFragment extends BasePullToRefresh } @Override - public IStatusesAdapter getListAdapter() { + public IStatusesListAdapter getListAdapter() { return mAdapter; } @@ -456,7 +456,7 @@ abstract class BaseStatusesStaggeredGridFragment extends BasePullToRefresh protected abstract void loadMoreStatuses(); - protected abstract IStatusesAdapter newAdapterInstance(); + protected abstract IStatusesListAdapter newAdapterInstance(); @Override protected void onReachedBottom() { @@ -548,7 +548,7 @@ abstract class BaseStatusesStaggeredGridFragment extends BasePullToRefresh static class RemoveUnreadCountsTask extends AsyncTask { private final List read_positions; - private final IStatusesAdapter adapter; + private final IStatusesListAdapter adapter; private final BaseStatusesStaggeredGridFragment fragment; RemoveUnreadCountsTask(final List read_positions, final BaseStatusesStaggeredGridFragment fragment) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesListFragment.java index 3e0a28788..c26ac5a86 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesListFragment.java @@ -29,7 +29,7 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.loader.support.DummyParcelableStatusesLoader; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.util.ArrayUtils; @@ -135,7 +135,7 @@ public abstract class ParcelableStatusesListFragment extends BaseStatusesListFra @Override public void onRefreshFromStart() { if (isRefreshing()) return; - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); final int count = adapter.getCount(); final ParcelableStatus status = count > 0 ? adapter.getStatus(0) : null; if (status != null) { @@ -170,14 +170,14 @@ public abstract class ParcelableStatusesListFragment extends BaseStatusesListFra @Override protected final long[] getNewestStatusIds() { - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); final long last_id = adapter.getCount() > 0 ? adapter.getStatus(0).id : -1; return last_id > 0 ? new long[]{last_id} : null; } @Override protected final long[] getOldestStatusIds() { - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); final ParcelableStatus status = adapter.getLastStatus(); final long last_id = status != null ? status.id : -1; return last_id > 0 ? new long[]{last_id} : null; @@ -200,7 +200,7 @@ public abstract class ParcelableStatusesListFragment extends BaseStatusesListFra @Override protected void loadMoreStatuses() { if (isRefreshing()) return; - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); final ParcelableStatus status = adapter.getLastStatus(); if (status != null) { getStatuses(new long[]{status.account_id}, new long[]{status.id}, null); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/RetweetsOfMeFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/RetweetsOfMeFragment.java index 8fb12b5d1..9d6f10a84 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/RetweetsOfMeFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/RetweetsOfMeFragment.java @@ -23,7 +23,7 @@ import android.content.Context; import android.os.Bundle; import android.support.v4.content.Loader; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.loader.support.RetweetsOfMeLoader; import org.mariotaku.twidere.model.ParcelableStatus; @@ -45,7 +45,7 @@ public class RetweetsOfMeFragment extends ParcelableStatusesListFragment { @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); adapter.setIndicateMyStatusDisabled(false); adapter.setFiltersEnabled(true); adapter.setIgnoredFilterFields(true, false, false, false, false); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/SearchStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/SearchStatusesFragment.java index 4a1aa3424..5fa482e30 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/SearchStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/SearchStatusesFragment.java @@ -28,7 +28,7 @@ import android.support.v4.content.Loader; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.loader.support.TweetSearchLoader; import org.mariotaku.twidere.model.ParcelableStatus; @@ -44,7 +44,7 @@ public class SearchStatusesFragment extends ParcelableStatusesListFragment { final long sinceId = args.getLong(EXTRA_SINCE_ID, -1); final String query = args.getString(EXTRA_QUERY); final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1); - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); adapter.setHighlightKeyword(query.split(" ")); return new TweetSearchLoader(getActivity(), accountId, query, maxId, sinceId, getData(), getSavedStatusesFileArgs(), tabPosition); @@ -53,7 +53,7 @@ public class SearchStatusesFragment extends ParcelableStatusesListFragment { @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); adapter.setFiltersEnabled(true); adapter.setIgnoredFilterFields(false, false, false, false, false); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java index b4fc339f5..2ee8636ad 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java @@ -72,7 +72,7 @@ import org.mariotaku.twidere.activity.support.AccountSelectorActivity; import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity; import org.mariotaku.twidere.activity.support.LinkHandlerActivity; import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.model.Account; import org.mariotaku.twidere.model.Account.AccountWithCredentials; @@ -718,7 +718,7 @@ public class StatusFragment extends ParcelableStatusesListFragment implements On @Override public boolean scrollToStart() { if (mListView == null) return false; - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); scrollListToPosition(mListView, adapter.getCount() + mListView.getFooterViewsCount() - 1, 0); return true; } @@ -773,17 +773,13 @@ public class StatusFragment extends ParcelableStatusesListFragment implements On } case MENU_QUOTE: { final Intent intent = new Intent(INTENT_ACTION_QUOTE); - final Bundle bundle = new Bundle(); - bundle.putParcelable(EXTRA_STATUS, status); - intent.putExtras(bundle); + intent.putExtra(EXTRA_STATUS, status); startActivity(intent); break; } case MENU_REPLY: { final Intent intent = new Intent(INTENT_ACTION_REPLY); - final Bundle bundle = new Bundle(); - bundle.putParcelable(EXTRA_STATUS, status); - intent.putExtras(bundle); + intent.putExtra(EXTRA_STATUS, status); startActivity(intent); break; } @@ -940,7 +936,7 @@ public class StatusFragment extends ParcelableStatusesListFragment implements On mConversationTask.cancel(true); return; } - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); final int count = adapter.getCount(); final ParcelableStatus status; if (count == 0) { @@ -980,7 +976,7 @@ public class StatusFragment extends ParcelableStatusesListFragment implements On private void updateConversationInfo() { final boolean has_converstion = mStatus != null && mStatus.in_reply_to_status_id > 0; - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); final boolean load_not_finished = adapter.isEmpty() || adapter.getStatus(adapter.getCount() - 1).in_reply_to_status_id > 0; final boolean enable = has_converstion && load_not_finished; @@ -1037,7 +1033,7 @@ public class StatusFragment extends ParcelableStatusesListFragment implements On @Override public void run() { final String uri = getMapStaticImageUri(mLocation.latitude, mLocation.longitude, mView); - mLoader.displayPreviewImage(mView, uri); + mLoader.displayPreviewImage(uri, mView); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserFavoritesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserFavoritesFragment.java index 6c64aa42b..9948aeee1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserFavoritesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserFavoritesFragment.java @@ -29,7 +29,7 @@ import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.content.Loader; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.loader.support.UserFavoritesLoader; import org.mariotaku.twidere.model.ParcelableStatus; @@ -82,7 +82,7 @@ public class UserFavoritesFragment extends ParcelableStatusesListFragment { final String screen_name = args != null ? args.getString(EXTRA_SCREEN_NAME) : null; final boolean is_my_timeline = user_id > 0 ? account_id == user_id : account_id == getAccountId(getActivity(), screen_name); - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); adapter.setFavoritesHightlightDisabled(is_my_timeline); adapter.setFiltersEnabled(false); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListTimelineFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListTimelineFragment.java index b3baa76c2..0d35dcd54 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListTimelineFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListTimelineFragment.java @@ -23,7 +23,7 @@ import android.content.Context; import android.os.Bundle; import android.support.v4.content.Loader; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.loader.support.UserListTimelineLoader; import org.mariotaku.twidere.model.ParcelableStatus; @@ -49,7 +49,7 @@ public class UserListTimelineFragment extends ParcelableStatusesListFragment { @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); adapter.setFiltersEnabled(true); adapter.setIgnoredFilterFields(false, false, false, false, false); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment.java index e391725a1..bd1257b48 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment.java @@ -23,7 +23,7 @@ import android.content.Context; import android.os.Bundle; import android.support.v4.content.Loader; -import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter; import org.mariotaku.twidere.loader.support.UserTimelineLoader; import org.mariotaku.twidere.model.ParcelableStatus; @@ -56,7 +56,7 @@ public class UserTimelineFragment extends ParcelableStatusesListFragment { final String screenName = args != null ? args.getString(EXTRA_SCREEN_NAME) : null; final boolean isMyTimeline = userId > 0 ? accountId == userId : accountId == getAccountId(getActivity(), screenName); - final IStatusesAdapter> adapter = getListAdapter(); + final IStatusesListAdapter> adapter = getListAdapter(); adapter.setIndicateMyStatusDisabled(isMyTimeline); adapter.setFiltersEnabled(!isMyTimeline); adapter.setIgnoredFilterFields(true, false, false, false, false); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment2.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment2.java new file mode 100644 index 000000000..e21dc9bb1 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserTimelineFragment2.java @@ -0,0 +1,339 @@ +package org.mariotaku.twidere.fragment.support; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.Loader; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.Adapter; +import android.support.v7.widget.RecyclerView.OnScrollListener; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.pkmmte.view.CircularImageView; + +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration; +import org.mariotaku.twidere.adapter.iface.IStatusesAdapter; +import org.mariotaku.twidere.app.TwidereApplication; +import org.mariotaku.twidere.loader.support.UserTimelineLoader; +import org.mariotaku.twidere.model.ParcelableMedia; +import org.mariotaku.twidere.model.ParcelableStatus; +import org.mariotaku.twidere.util.ImageLoaderWrapper; +import org.mariotaku.twidere.util.ImageLoadingHandler; +import org.mariotaku.twidere.util.ThemeUtils; +import org.mariotaku.twidere.util.Utils; +import org.mariotaku.twidere.view.ShortTimeView; + +import java.util.List; +import java.util.Locale; + +/** + * Created by mariotaku on 14/11/5. + */ +public class UserTimelineFragment2 extends BaseSupportFragment + implements LoaderCallbacks> { + + private RecyclerView mRecyclerView; + private ProgressBar mProgress; + + private ParcelableTimelineAdapter mAdapter; + private OnScrollListener mOnScrollListener = new OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + } + }; + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + final View view = getView(); + assert view != null; + final Context context = view.getContext(); + final boolean compact = Utils.isCompactCards(context); + mAdapter = new ParcelableTimelineAdapter(context, compact); + final LinearLayoutManager layoutManager = new LinearLayoutManager(context); + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + mRecyclerView.setLayoutManager(layoutManager); + if (compact) { + mRecyclerView.addItemDecoration(new DividerItemDecoration(context, layoutManager.getOrientation())); + } + mRecyclerView.setAdapter(mAdapter); + mRecyclerView.setOnScrollListener(mOnScrollListener); + getLoaderManager().initLoader(0, getArguments(), this); + setListShown(false); + } + + public void setListShown(boolean shown) { + mRecyclerView.setVisibility(shown ? View.VISIBLE : View.GONE); + mProgress.setVisibility(shown ? View.GONE : View.VISIBLE); + } + + public int getStatuses(final long maxId, final long sinceId) { + final Bundle args = new Bundle(getArguments()); + args.putLong(EXTRA_MAX_ID, maxId); + args.putLong(EXTRA_SINCE_ID, sinceId); + getLoaderManager().restartLoader(0, args, this); + return -1; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list); + mProgress = (ProgressBar) view.findViewById(android.R.id.progress); + } + + @Override + protected void fitSystemWindows(Rect insets) { + super.fitSystemWindows(insets); + mRecyclerView.setClipToPadding(false); + mRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom); + } + + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_recycler_view, container, false); + } + + @Override + public Loader> onCreateLoader(int id, Bundle args) { + final Context context = getActivity(); + final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1); + final long maxId = args.getLong(EXTRA_MAX_ID, -1); + final long sinceId = args.getLong(EXTRA_SINCE_ID, -1); + final long userId = args.getLong(EXTRA_USER_ID, -1); + final String screenName = args.getString(EXTRA_SCREEN_NAME); + final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1); + return new UserTimelineLoader(context, accountId, userId, screenName, maxId, sinceId, null, + null, tabPosition); + } + + @Override + public void onLoadFinished(Loader> loader, List data) { + mAdapter.setData(data); + setListShown(true); + } + + @Override + public void onLoaderReset(Loader> loader) { + mAdapter.setData(null); + } + + private static class ParcelableTimelineAdapter extends Adapter implements IStatusesAdapter, OnClickListener { + + private static final int ITEM_VIEW_TYPE_STATUS = 1; + private static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 2; + + private final Context mContext; + private final LayoutInflater mInflater; + private final ImageLoaderWrapper mImageLoader; + private final ImageLoadingHandler mLoadingHandler; + private final int mCardLayoutResource; + private List mData; + private boolean mHasMoreItem; + + ParcelableTimelineAdapter(Context context, boolean compact) { + mContext = context; + mInflater = LayoutInflater.from(context); + mImageLoader = TwidereApplication.getInstance(context).getImageLoaderWrapper(); + mLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress); + if (compact) { + mCardLayoutResource = R.layout.card_item_list_status_compat; + } else { + mCardLayoutResource = R.layout.card_item_list_status; + } + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + switch (viewType) { + case ITEM_VIEW_TYPE_STATUS: { + final View view = mInflater.inflate(mCardLayoutResource, parent, false); + return new MediaTimelineViewHolder(this, view); + } + case ITEM_VIEW_TYPE_LOAD_INDICATOR: { + final View view = mInflater.inflate(R.layout.card_item_load_indicator, parent, false); + return new LoadIndicatorViewHolder(view); + } + } + throw new IllegalStateException("Unknown view type " + viewType); + } + + public void setHasMoreItem(boolean hasMoreItem) { + if (mHasMoreItem == hasMoreItem) return; + mHasMoreItem = hasMoreItem; + notifyDataSetChanged(); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + if (mData == null) return; + if (holder instanceof MediaTimelineViewHolder) { + ((MediaTimelineViewHolder) holder).displayStatus(this, getStatus(position)); + } + } + + public void setData(List data) { + mData = data; + notifyDataSetChanged(); + } + + @Override + public int getItemViewType(int position) { + if (position == getItemCount() - 1) { + return ITEM_VIEW_TYPE_LOAD_INDICATOR; + } + return ITEM_VIEW_TYPE_STATUS; + } + + @Override + public int getItemCount() { + if (mData == null) return mHasMoreItem ? 1 : 0; + return mData.size() + (mHasMoreItem ? 1 : 0); + } + + public ImageLoaderWrapper getImageLoader() { + return mImageLoader; + } + + public Context getContext() { + return mContext; + } + + public ImageLoadingHandler getImageLoadingHandler() { + return mLoadingHandler; + } + + @Override + public void onClick(View v) { + + } + + + @Override + public ParcelableStatus getStatus(int position) { + if (mData == null || (mHasMoreItem && position == mData.size() - 1)) return null; + return mData.get(position); + } + } + + private static class LoadIndicatorViewHolder extends ViewHolder { + public LoadIndicatorViewHolder(View view) { + super(view); + } + } + + private static class MediaTimelineViewHolder extends ViewHolder implements OnClickListener { + + private final IStatusesAdapter adapter; + + private final ImageView mediaPreviewView; + private final CircularImageView profileImageView; + private final TextView textView; + private final TextView nameView; + private final ShortTimeView timeView; + private final View mediaPreviewContainer; + private final View replyIndicator, retweetIndicator, favoriteIndicator; + private final TextView replyCountView, retweetCountView, favoriteCountView; + + public MediaTimelineViewHolder(IStatusesAdapter adapter, View itemView) { + super(itemView); + this.adapter = adapter; + itemView.findViewById(R.id.item_content).setOnClickListener(this); + profileImageView = (CircularImageView) itemView.findViewById(R.id.profile_image); + textView = (TextView) itemView.findViewById(R.id.text); + nameView = (TextView) itemView.findViewById(R.id.name); + timeView = (ShortTimeView) itemView.findViewById(R.id.time); + + mediaPreviewContainer = itemView.findViewById(R.id.media_preview_container); + mediaPreviewView = (ImageView) itemView.findViewById(R.id.media_preview); + + replyIndicator = itemView.findViewById(R.id.reply_indicator); + retweetIndicator = itemView.findViewById(R.id.retweet_indicator); + favoriteIndicator = itemView.findViewById(R.id.favorite_indicator); + + replyCountView = (TextView) itemView.findViewById(R.id.reply_count); + retweetCountView = (TextView) itemView.findViewById(R.id.retweet_count); + favoriteCountView = (TextView) itemView.findViewById(R.id.favorite_count); + + profileImageView.setSelectorColor(ThemeUtils.getUserHighlightColor(itemView.getContext())); + + itemView.setOnClickListener(this); + profileImageView.setOnClickListener(this); + mediaPreviewContainer.setOnClickListener(this); + replyIndicator.setOnClickListener(this); + retweetIndicator.setOnClickListener(this); + favoriteIndicator.setOnClickListener(this); + } + + public void displayStatus(ParcelableTimelineAdapter adapter, ParcelableStatus status) { + final ImageLoaderWrapper loader = adapter.getImageLoader(); + final Context context = adapter.getContext(); + final ParcelableMedia[] media = status.media; + + nameView.setText(status.user_name); + timeView.setTime(status.timestamp); + loader.displayProfileImage(profileImageView, status.user_profile_image_url); + +// profileImageView.setBorderColor(UserColorNicknameUtils.getUserColor(context, status.user_id)); + if (media != null && media.length > 0) { + final ParcelableMedia firstMedia = media[0]; + if (status.text_plain.codePointCount(0, status.text_plain.length()) == firstMedia.end) { + textView.setText(status.text_unescaped.substring(0, firstMedia.start)); + } else { + textView.setText(status.text_unescaped); + } + loader.displayPreviewImageWithCredentials(mediaPreviewView, firstMedia.media_url, + status.account_id, adapter.getImageLoadingHandler()); + mediaPreviewContainer.setVisibility(View.VISIBLE); + } else { + loader.cancelDisplayTask(mediaPreviewView); + textView.setText(status.text_unescaped); + mediaPreviewContainer.setVisibility(View.GONE); + } + retweetIndicator.setActivated(status.is_retweet); + favoriteIndicator.setActivated(status.is_favorite); + + replyCountView.setVisibility(status.reply_count > 0 ? View.VISIBLE : View.INVISIBLE); + retweetCountView.setVisibility(status.retweet_count > 0 ? View.VISIBLE : View.INVISIBLE); + favoriteCountView.setVisibility(status.favorite_count > 0 ? View.VISIBLE : View.INVISIBLE); + replyCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), status.reply_count)); + retweetCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), status.retweet_count)); + favoriteCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), status.favorite_count)); + } + + @Override + public void onClick(View v) { + final Context context = itemView.getContext(); + final ParcelableStatus status = adapter.getStatus(getPosition()); + switch (v.getId()) { + case R.id.item_content: { + Utils.openStatus(context, status); + break; + } + case R.id.profile_image: { + Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name); + break; + } + case R.id.reply_indicator: { + final Intent intent = new Intent(INTENT_ACTION_REPLY); + intent.setPackage(context.getPackageName()); + intent.putExtra(EXTRA_STATUS, status); + context.startActivity(intent); + break; + } + } + } + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/preference/AccountsListPreference.java b/twidere/src/main/java/org/mariotaku/twidere/preference/AccountsListPreference.java index fd7a115ce..6843c8368 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/preference/AccountsListPreference.java +++ b/twidere/src/main/java/org/mariotaku/twidere/preference/AccountsListPreference.java @@ -21,7 +21,6 @@ package org.mariotaku.twidere.preference; import android.content.Context; import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -51,6 +50,7 @@ import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.model.Account; import org.mariotaku.twidere.task.AsyncTask; import org.mariotaku.twidere.util.ImageLoaderWrapper; +import org.mariotaku.twidere.util.Utils; import java.util.List; @@ -102,8 +102,11 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen private final Account mAccount; private final SharedPreferences mSwitchPreference; + private final ImageLoaderWrapper mImageLoader; + private final String mSwitchKey; private final boolean mSwitchDefault; + private Switch mToggle; public AccountItemPreference(final Context context, final Account account, final String switchKey, final boolean switchDefault) { @@ -113,6 +116,8 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen final String switchPreferenceName = ACCOUNT_PREFERENCES_NAME_PREFIX + account.account_id; mAccount = account; mSwitchPreference = context.getSharedPreferences(switchPreferenceName, Context.MODE_PRIVATE); + final TwidereApplication app = TwidereApplication.getInstance(context); + mImageLoader = app.getImageLoaderWrapper(); mSwitchKey = switchKey; mSwitchDefault = switchDefault; mSwitchPreference.registerOnSharedPreferenceChangeListener(this); @@ -133,7 +138,8 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen @Override public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) { - setIcon(new BitmapDrawable(getContext().getResources(), loadedImage)); + final Bitmap roundedBitmap = Utils.getCircleBitmap(loadedImage); + setIcon(new BitmapDrawable(getContext().getResources(), roundedBitmap)); } @Override @@ -157,9 +163,7 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen setTitle(mAccount.name); setSummary(String.format("@%s", mAccount.screen_name)); setIcon(R.drawable.ic_profile_image_default); - final TwidereApplication app = TwidereApplication.getInstance(getContext()); - final ImageLoaderWrapper loader = app.getImageLoaderWrapper(); - loader.loadProfileImage(mAccount.profile_image_url, this); + mImageLoader.loadProfileImage(mAccount.profile_image_url, this); } @Override @@ -168,6 +172,7 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen view.findViewById(R.id.settings).setOnClickListener(this); final Switch toggle = (Switch) view.findViewById(android.R.id.toggle); toggle.setOnCheckedChangeListener(this); + mToggle = toggle; return view; } @@ -176,7 +181,8 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen super.onBindView(view); final View iconView = view.findViewById(android.R.id.icon); if (iconView instanceof ImageView) { - ((ImageView) iconView).setScaleType(ScaleType.FIT_CENTER); + final ImageView imageView = (ImageView) iconView; + imageView.setScaleType(ScaleType.CENTER_CROP); } final View titleView = view.findViewById(android.R.id.title); if (titleView instanceof TextView) { @@ -194,7 +200,9 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen @Override public boolean onPreferenceClick(Preference preference) { - + if (mToggle != null) { + mToggle.toggle(); + } return true; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/preference/ThemeBackgroundPreference.java b/twidere/src/main/java/org/mariotaku/twidere/preference/ThemeBackgroundPreference.java index b63adbddd..9505c2e8f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/preference/ThemeBackgroundPreference.java +++ b/twidere/src/main/java/org/mariotaku/twidere/preference/ThemeBackgroundPreference.java @@ -175,6 +175,13 @@ public class ThemeBackgroundPreference extends DialogPreference implements Const ViewAccessor.setBackground(mAlphaPreview, new AlphaPatternDrawable(patternSize)); updateAlphaVisibility(); updateAlphaPreview(); + + final int checkedIdx = findIndexOfValue(getPersistedString(mValue)); + if (checkedIdx < 0) { + listView.clearChoices(); + } else { + listView.setItemChecked(checkedIdx, true); + } } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/ImageLoaderWrapper.java b/twidere/src/main/java/org/mariotaku/twidere/util/ImageLoaderWrapper.java index 368e6920b..b73031943 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/ImageLoaderWrapper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/ImageLoaderWrapper.java @@ -31,13 +31,16 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; import org.mariotaku.twidere.util.imageloader.AccountExtra; +import org.mariotaku.twidere.util.imageloader.OvalBitmapDisplayer; import static org.mariotaku.twidere.util.Utils.getBestBannerType; public class ImageLoaderWrapper implements Constants { private final ImageLoader mImageLoader; - private final DisplayImageOptions mProfileImageDisplayOptions, mImageDisplayOptions, mBannerDisplayOptions; + private final DisplayImageOptions mProfileImageDisplayOptions; + private final DisplayImageOptions mOvalProfileImageDisplayOptions; + private final DisplayImageOptions mImageDisplayOptions, mBannerDisplayOptions; public ImageLoaderWrapper(final ImageLoader loader) { mImageLoader = loader; @@ -49,6 +52,15 @@ public class ImageLoaderWrapper implements Constants { profileOptsBuilder.showImageOnLoading(R.drawable.ic_profile_image_default); profileOptsBuilder.bitmapConfig(Bitmap.Config.ARGB_8888); profileOptsBuilder.resetViewBeforeLoading(true); + final DisplayImageOptions.Builder ovalProfileOptsBuilder = new DisplayImageOptions.Builder(); + ovalProfileOptsBuilder.cacheInMemory(true); + ovalProfileOptsBuilder.cacheOnDisk(true); + ovalProfileOptsBuilder.showImageForEmptyUri(R.drawable.ic_profile_image_default); + ovalProfileOptsBuilder.showImageOnFail(R.drawable.ic_profile_image_default); + ovalProfileOptsBuilder.showImageOnLoading(R.drawable.ic_profile_image_default); + ovalProfileOptsBuilder.bitmapConfig(Bitmap.Config.ARGB_8888); + ovalProfileOptsBuilder.displayer(new OvalBitmapDisplayer()); + ovalProfileOptsBuilder.resetViewBeforeLoading(true); final DisplayImageOptions.Builder imageOptsBuilder = new DisplayImageOptions.Builder(); imageOptsBuilder.cacheInMemory(true); imageOptsBuilder.cacheOnDisk(true); @@ -61,6 +73,7 @@ public class ImageLoaderWrapper implements Constants { bannerOptsBuilder.displayer(new FadeInBitmapDisplayer(200, true, true, false)); mProfileImageDisplayOptions = profileOptsBuilder.build(); + mOvalProfileImageDisplayOptions = ovalProfileOptsBuilder.build(); mImageDisplayOptions = imageOptsBuilder.build(); mBannerDisplayOptions = bannerOptsBuilder.build(); } @@ -73,8 +86,8 @@ public class ImageLoaderWrapper implements Constants { mImageLoader.clearMemoryCache(); } - public void displayPreviewImage(final ImageView view, final String url) { - mImageLoader.displayImage(url, view, mImageDisplayOptions); + public void displayPreviewImage(final String uri, final ImageView view) { + mImageLoader.displayImage(uri, view, mImageDisplayOptions); } public void displayPreviewImage(final ImageView view, final String url, final ImageLoadingHandler loadingHandler) { @@ -103,6 +116,10 @@ public class ImageLoaderWrapper implements Constants { mImageLoader.loadImage(url, mProfileImageDisplayOptions, listener); } + public void displayOvalProfileImage(final String url, final ImageView view) { + mImageLoader.displayImage(url, view, mOvalProfileImageDisplayOptions); + } + public void cancelDisplayTask(ImageView imageView) { mImageLoader.cancelDisplayTask(imageView); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/MessagesManager.java b/twidere/src/main/java/org/mariotaku/twidere/util/MessagesManager.java index 7e7fa9c30..216d99d8c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/MessagesManager.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/MessagesManager.java @@ -24,150 +24,129 @@ import android.content.Context; import android.content.SharedPreferences; import org.mariotaku.twidere.Constants; -import org.mariotaku.twidere.activity.support.BaseSupportActivity; -import org.mariotaku.twidere.activity.support.HomeActivity; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; public final class MessagesManager implements Constants { - private final Set mMessageCallbacks = Collections.synchronizedSet(new HashSet()); - private final Context mContext; - private final SharedPreferences mPreferences; + private final Context mContext; + private final SharedPreferences mPreferences; - public MessagesManager(final Context context) { - mContext = context; - mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - } + public MessagesManager(final Context context) { + mContext = context; + mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + } - public boolean addMessageCallback(final Activity activity) { - if (activity == null) return false; - return mMessageCallbacks.add(activity); - } + public boolean addMessageCallback(final Activity activity) { + if (activity == null) return false; + return true; + } - public boolean removeMessageCallback(final Activity activity) { - if (activity == null) return false; - return mMessageCallbacks.remove(activity); - } + public boolean removeMessageCallback(final Activity activity) { + if (activity == null) return false; + return true; + } - public void showErrorMessage(final CharSequence message, final boolean long_message) { - final Activity best = getBestActivity(); - if (best != null) { - Utils.showErrorMessage(best, message, long_message); - return; - } - if (showToast()) { - Utils.showErrorMessage(mContext, message, long_message); - return; - } - } + public void showErrorMessage(final CharSequence message, final boolean long_message) { + final Activity best = getBestActivity(); + if (best != null) { + Utils.showErrorMessage(best, message, long_message); + return; + } + if (showToast()) { + Utils.showErrorMessage(mContext, message, long_message); + return; + } + } - public void showErrorMessage(final int actionRes, final Exception e, final boolean long_message) { - final String action = mContext.getString(actionRes); - final Activity best = getBestActivity(); - if (best != null) { - Utils.showErrorMessage(best, action, e, long_message); - return; - } - if (showToast()) { - Utils.showErrorMessage(mContext, action, e, long_message); - return; - } - } + public void showErrorMessage(final int actionRes, final Exception e, final boolean long_message) { + final String action = mContext.getString(actionRes); + final Activity best = getBestActivity(); + if (best != null) { + Utils.showErrorMessage(best, action, e, long_message); + return; + } + if (showToast()) { + Utils.showErrorMessage(mContext, action, e, long_message); + return; + } + } - public void showErrorMessage(final int action_res, final String message, final boolean long_message) { - final String action = mContext.getString(action_res); - final Activity best = getBestActivity(); - if (best != null) { - Utils.showErrorMessage(best, action, message, long_message); - return; - } - if (showToast()) { - Utils.showErrorMessage(mContext, action, message, long_message); - return; - } - } + public void showErrorMessage(final int action_res, final String message, final boolean longMessage) { + final String action = mContext.getString(action_res); + final Activity best = getBestActivity(); + if (best != null) { + Utils.showErrorMessage(best, action, message, longMessage); + return; + } + if (showToast()) { + Utils.showErrorMessage(mContext, action, message, longMessage); + return; + } + } - public void showInfoMessage(final CharSequence message, final boolean long_message) { - final Activity best = getBestActivity(); - if (best != null) { - Utils.showInfoMessage(best, message, long_message); - return; - } - if (showToast()) { - Utils.showInfoMessage(mContext, message, long_message); - return; - } - } + public void showInfoMessage(final CharSequence message, final boolean longMessage) { + final Activity best = getBestActivity(); + if (best != null) { + Utils.showInfoMessage(best, message, longMessage); + return; + } + if (showToast()) { + Utils.showInfoMessage(mContext, message, longMessage); + return; + } + } - public void showInfoMessage(final int message_res, final boolean long_message) { - final Activity best = getBestActivity(); - if (best != null) { - Utils.showInfoMessage(best, message_res, long_message); - return; - } - if (showToast()) { - Utils.showInfoMessage(mContext, message_res, long_message); - return; - } - } + public void showInfoMessage(final int messageRes, final boolean longMessage) { + final Activity best = getBestActivity(); + if (best != null) { + Utils.showInfoMessage(best, messageRes, longMessage); + return; + } + if (showToast()) { + Utils.showInfoMessage(mContext, messageRes, longMessage); + return; + } + } - public void showOkMessage(final CharSequence message, final boolean long_message) { - final Activity best = getBestActivity(); - if (best != null) { - Utils.showOkMessage(best, message, long_message); - return; - } - if (showToast()) { - Utils.showOkMessage(mContext, message, long_message); - } - } + public void showOkMessage(final CharSequence message, final boolean longMessage) { + final Activity best = getBestActivity(); + if (best != null) { + Utils.showOkMessage(best, message, longMessage); + return; + } + if (showToast()) { + Utils.showOkMessage(mContext, message, longMessage); + } + } - public void showOkMessage(final int message_res, final boolean long_message) { - final Activity best = getBestActivity(); - if (best != null) { - Utils.showOkMessage(best, message_res, long_message); - return; - } - if (showToast()) { - Utils.showOkMessage(mContext, message_res, long_message); - return; - } - } + public void showOkMessage(final int messageRes, final boolean longMessage) { + final Activity best = getBestActivity(); + if (best != null) { + Utils.showOkMessage(best, messageRes, longMessage); + return; + } + if (showToast()) { + Utils.showOkMessage(mContext, messageRes, longMessage); + return; + } + } - public void showWarnMessage(final int message_res, final boolean long_message) { - final Activity best = getBestActivity(); - if (best != null) { - Utils.showWarnMessage(best, message_res, long_message); - return; - } - if (showToast()) { - Utils.showWarnMessage(mContext, message_res, long_message); - } - } + public void showWarnMessage(final int messageRes, final boolean longMessage) { + final Activity best = getBestActivity(); + if (best != null) { + Utils.showWarnMessage(best, messageRes, longMessage); + return; + } + if (showToast()) { + Utils.showWarnMessage(mContext, messageRes, longMessage); + } + } - private Activity getBestActivity() { - for (final Activity activity : mMessageCallbacks) { - if (activity instanceof BaseSupportActivity) { - final BaseSupportActivity base = (BaseSupportActivity) activity; - if (base.isOnTop()) return base; - } - } - for (final Activity activity : mMessageCallbacks) { - if (activity instanceof HomeActivity) { - final HomeActivity home = (HomeActivity) activity; - if (home.isVisible()) return home; - } - } - for (final Activity activity : mMessageCallbacks) - if (ThemeUtils.isFloatingWindow(activity)) return activity; - return null; - } + private Activity getBestActivity() { + return null; + } - private boolean showToast() { - return mPreferences.getBoolean(KEY_BACKGROUND_TOAST_NOTIFICATION, false); - } + private boolean showToast() { + return true; + } } 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 d9555fa05..85e703698 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -41,8 +41,12 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -139,7 +143,7 @@ import org.mariotaku.twidere.fragment.support.UserListsListFragment; import org.mariotaku.twidere.fragment.support.UserMediaTimelineFragment; import org.mariotaku.twidere.fragment.support.UserMentionsFragment; import org.mariotaku.twidere.fragment.support.UserProfileFragmentOld; -import org.mariotaku.twidere.fragment.support.UserTimelineFragment; +import org.mariotaku.twidere.fragment.support.UserTimelineFragment2; import org.mariotaku.twidere.fragment.support.UsersListFragment; import org.mariotaku.twidere.graphic.PaddingDrawable; import org.mariotaku.twidere.model.Account; @@ -676,6 +680,27 @@ public final class Utils implements Constants, TwitterConstants { } } + public static Bitmap getCircleBitmap(Bitmap bitmap) { + final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), + Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(output); + + final int color = Color.RED; + final Paint paint = new Paint(); + final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + final RectF rectF = new RectF(rect); + + paint.setAntiAlias(true); + canvas.drawARGB(0, 0, 0, 0); + paint.setColor(color); + canvas.drawOval(rectF, paint); + + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, rect, rect, paint); + + return output; + } + public static Fragment createFragmentForIntent(final Context context, final Intent intent) { final long start = System.currentTimeMillis(); intent.setExtrasClassLoader(context.getClassLoader()); @@ -721,7 +746,7 @@ public final class Utils implements Constants, TwitterConstants { break; } case LINK_ID_USER_TIMELINE: { - fragment = new UserTimelineFragment(); + fragment = new UserTimelineFragment2(); final String paramScreenName = uri.getQueryParameter(QUERY_PARAM_SCREEN_NAME); final String paramUserId = uri.getQueryParameter(QUERY_PARAM_USER_ID); if (!args.containsKey(EXTRA_SCREEN_NAME)) { @@ -2990,8 +3015,8 @@ public final class Utils implements Constants, TwitterConstants { activity.startActivity(intent); } - public static void openStatus(final Activity activity, final ParcelableStatus status) { - if (activity == null || status == null) return; + public static void openStatus(final Context context, final ParcelableStatus status) { + if (context == null || status == null) return; final long account_id = status.account_id, status_id = status.id; final Bundle extras = new Bundle(); extras.putParcelable(EXTRA_STATUS, status); @@ -3001,9 +3026,9 @@ public final class Utils implements Constants, TwitterConstants { builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(account_id)); builder.appendQueryParameter(QUERY_PARAM_STATUS_ID, String.valueOf(status_id)); final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build()); - intent.setExtrasClassLoader(activity.getClassLoader()); + intent.setExtrasClassLoader(context.getClassLoader()); intent.putExtras(extras); - activity.startActivity(intent); + context.startActivity(intent); } public static void openStatuses(final Activity activity, final List statuses) { @@ -3302,21 +3327,21 @@ public final class Utils implements Constants, TwitterConstants { activity.startActivity(intent); } - public static void openUserProfile(final Activity activity, final long account_id, final long user_id, - final String screen_name) { - if (activity == null || account_id <= 0 || user_id <= 0 && isEmpty(screen_name)) return; + public static void openUserProfile(final Context context, final long accountId, final long userId, + final String screenName) { + if (context == null || accountId <= 0 || userId <= 0 && isEmpty(screenName)) return; final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER); - builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(account_id)); - if (user_id > 0) { - builder.appendQueryParameter(QUERY_PARAM_USER_ID, String.valueOf(user_id)); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId)); + if (userId > 0) { + builder.appendQueryParameter(QUERY_PARAM_USER_ID, String.valueOf(userId)); } - if (screen_name != null) { - builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screen_name); + if (screenName != null) { + builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName); } final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build()); - activity.startActivity(intent); + context.startActivity(intent); } public static void openUserProfile(final Activity activity, final ParcelableUser user) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/imageloader/OvalBitmapDisplayer.java b/twidere/src/main/java/org/mariotaku/twidere/util/imageloader/OvalBitmapDisplayer.java new file mode 100644 index 000000000..452d30246 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/util/imageloader/OvalBitmapDisplayer.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright 2011-2013 Sergey Tarasevich + * + * 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.util.imageloader; + +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; + +import com.nostra13.universalimageloader.core.assist.LoadedFrom; +import com.nostra13.universalimageloader.core.display.BitmapDisplayer; +import com.nostra13.universalimageloader.core.imageaware.ImageAware; +import com.nostra13.universalimageloader.core.imageaware.ImageViewAware; + +/** + * Can display bitmap with rounded corners. This implementation works only with ImageViews wrapped + * in ImageViewAware. + *
+ * This implementation is inspired by + * + * Romain Guy's article. It rounds images using custom drawable drawing. Original bitmap isn't changed. + *
+ *
+ * If this implementation doesn't meet your needs then consider + * RoundedImageView or + * CircularImageView projects for usage. + * + * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) + * @since 1.5.6 + */ +public class OvalBitmapDisplayer implements BitmapDisplayer { + + protected final int margin; + + public OvalBitmapDisplayer() { + this(0); + } + + public OvalBitmapDisplayer(int marginPixels) { + this.margin = marginPixels; + } + + @Override + public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { + if (!(imageAware instanceof ImageViewAware)) { + throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected."); + } + + imageAware.setImageDrawable(new OvalDrawable(bitmap, margin)); + } + + public static class OvalDrawable extends Drawable { + + protected final int margin; + + protected final RectF mRect = new RectF(), + mBitmapRect; + protected final BitmapShader bitmapShader; + protected final Paint paint; + + public OvalDrawable(Bitmap bitmap, int margin) { + this.margin = margin; + + bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + mBitmapRect = new RectF(margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin); + + paint = new Paint(); + paint.setAntiAlias(true); + paint.setShader(bitmapShader); + } + + @Override + protected void onBoundsChange(Rect bounds) { + super.onBoundsChange(bounds); + mRect.set(margin, margin, bounds.width() - margin, bounds.height() - margin); + + // Resize the original bitmap to fit the new bound + Matrix shaderMatrix = new Matrix(); + shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL); + bitmapShader.setLocalMatrix(shaderMatrix); + + } + + @Override + public void draw(Canvas canvas) { + canvas.drawOval(mRect, paint); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + } + + @Override + public void setColorFilter(ColorFilter cf) { + paint.setColorFilter(cf); + } + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/IconActionButton.java b/twidere/src/main/java/org/mariotaku/twidere/view/IconActionButton.java new file mode 100644 index 000000000..1c5757070 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/view/IconActionButton.java @@ -0,0 +1,49 @@ +package org.mariotaku.twidere.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.PorterDuff.Mode; +import android.util.AttributeSet; +import android.widget.ImageButton; + +import org.mariotaku.twidere.R; + +/** + * Created by mariotaku on 14/11/5. + */ +public class IconActionButton extends ImageButton { + + private final int mColor, mActivatedColor; + + public IconActionButton(Context context) { + this(context, null); + } + + public IconActionButton(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public IconActionButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + final TypedArray defaultValues = context.obtainStyledAttributes( + new int[]{android.R.attr.colorForeground, android.R.attr.colorActivatedHighlight}); + final int defaultColor = defaultValues.getColor(0, 0); + final int defaultActivatedColor = defaultValues.getColor(1, 0); + defaultValues.recycle(); + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IconActionButton); + mColor = a.getColor(R.styleable.IconActionButton_color, defaultColor); + mActivatedColor = a.getColor(R.styleable.IconActionButton_activatedColor, defaultActivatedColor); + a.recycle(); + updateColorFilter(); + } + + @Override + public void setActivated(boolean activated) { + super.setActivated(activated); + updateColorFilter(); + } + + private void updateColorFilter() { + setColorFilter(isActivated() ? mActivatedColor : mColor, Mode.SRC_ATOP); + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/iface/IForegroundView.java b/twidere/src/main/java/org/mariotaku/twidere/view/iface/IForegroundView.java index c57cde615..b20baaff5 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/iface/IForegroundView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/iface/IForegroundView.java @@ -19,13 +19,12 @@ package org.mariotaku.twidere.view.iface; -import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.Build; +import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; @@ -226,10 +225,9 @@ public interface IForegroundView { return who == mForeground; } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void dispatchDrawableHotspotChanged(float x, float y) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; - mForeground.setHotspot(x, y); + if (mForeground == null) return; + DrawableCompat.setHotspot(mForeground, x, y); } } } diff --git a/twidere/src/main/java/twitter4j/TwitterImpl.java b/twidere/src/main/java/twitter4j/TwitterImpl.java index d7b5b4a39..43391198a 100644 --- a/twidere/src/main/java/twitter4j/TwitterImpl.java +++ b/twidere/src/main/java/twitter4j/TwitterImpl.java @@ -1372,6 +1372,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter { final String sign_url = conf.getSigningRestBaseURL() + ENDPOINT_CONVERSATION_SHOW; final List paramsList = new ArrayList(); paramsList.add(INCLUDE_ENTITIES); + paramsList.add(INCLUDE_REPLY_COUNT); + paramsList.add(INCLUDE_DESCENDENT_REPLY_COUNT); paramsList.add(INCLUDE_MY_RETWEET); paramsList.add(new HttpParameter("id", statusId)); if (paging != null) { diff --git a/twidere/src/main/res/layout/card_item_list_status.xml b/twidere/src/main/res/layout/card_item_list_status.xml new file mode 100644 index 000000000..0f4b566c9 --- /dev/null +++ b/twidere/src/main/res/layout/card_item_list_status.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/card_item_list_status_compat.xml b/twidere/src/main/res/layout/card_item_list_status_compat.xml new file mode 100644 index 000000000..fcb3114fb --- /dev/null +++ b/twidere/src/main/res/layout/card_item_list_status_compat.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/card_item_load_indicator.xml b/twidere/src/main/res/layout/card_item_load_indicator.xml new file mode 100644 index 000000000..67d72cb8f --- /dev/null +++ b/twidere/src/main/res/layout/card_item_load_indicator.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/values-v21/styles.xml b/twidere/src/main/res/values-v21/styles.xml new file mode 100644 index 000000000..eba0615f6 --- /dev/null +++ b/twidere/src/main/res/values-v21/styles.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/values/attrs.xml b/twidere/src/main/res/values/attrs.xml index 9182d5add..d3b12cdec 100644 --- a/twidere/src/main/res/values/attrs.xml +++ b/twidere/src/main/res/values/attrs.xml @@ -2,6 +2,7 @@ + @@ -67,6 +68,10 @@ + + + + diff --git a/twidere/src/main/res/values/dimens.xml b/twidere/src/main/res/values/dimens.xml index 90a188fb5..e43215385 100644 --- a/twidere/src/main/res/values/dimens.xml +++ b/twidere/src/main/res/values/dimens.xml @@ -2,6 +2,7 @@ 48dp + 42dp 24dp 2dp 4dp @@ -72,5 +73,6 @@ 32dp 16dp 180dp + 48dp \ No newline at end of file diff --git a/twidere/src/main/res/values/styles.xml b/twidere/src/main/res/values/styles.xml index 045817e1c..37d6873c9 100644 --- a/twidere/src/main/res/values/styles.xml +++ b/twidere/src/main/res/values/styles.xml @@ -147,4 +147,11 @@ @integer/staggered_grid_columns_land + + + \ No newline at end of file diff --git a/twidere/src/main/res/values/themes.xml b/twidere/src/main/res/values/themes.xml index 4e0391617..e43d818d5 100644 --- a/twidere/src/main/res/values/themes.xml +++ b/twidere/src/main/res/values/themes.xml @@ -38,6 +38,7 @@ @style/Widget.StaggeredGridView + @style/Widget.CardActionButton @drawable/bg_card_item_dark #1a1a1a @@ -81,6 +82,7 @@ @style/Widget.StaggeredGridView + @style/Widget.Light.CardActionButton @drawable/bg_card_item_light #f8f8f8 @@ -150,6 +152,7 @@ @style/Widget.StaggeredGridView + @style/Widget.CardActionButton @drawable/bg_card_item_dark #1a1a1a @@ -178,6 +181,7 @@ @style/Widget.StaggeredGridView + @style/Widget.Light.CardActionButton @drawable/bg_card_item_light #f8f8f8 @@ -235,6 +239,7 @@ @style/Widget.Twidere.Viewer.ActionBar + @style/Widget.CardActionButton @drawable/bg_card_item_dark #1a1a1a @@ -332,6 +337,7 @@ @style/Widget.TabPageIndicator.TabItem.TextView.Dark + @style/Widget.CardActionButton @drawable/bg_card_item_dark #1a1a1a @@ -366,6 +372,7 @@ @style/Widget.TabPageIndicator.TabItem.TextView.Light + @style/Widget.Light.CardActionButton @drawable/bg_card_item_light #f8f8f8 @@ -400,6 +407,7 @@ @style/Widget.TabPageIndicator.TabItem.TextView.Light + @style/Widget.Light.CardActionButton @drawable/bg_card_item_light #f8f8f8 diff --git a/twidere/src/main/res/xml/settings_storage.xml b/twidere/src/main/res/xml/settings_storage.xml index cab7b63c6..a9682eabe 100644 --- a/twidere/src/main/res/xml/settings_storage.xml +++ b/twidere/src/main/res/xml/settings_storage.xml @@ -1,33 +1,37 @@ - + - - + - + - + - - + + + + + \ No newline at end of file