removed unused code

reduced status list item complexity
This commit is contained in:
Mariotaku Lee 2017-03-03 14:28:55 +08:00
parent ce02395841
commit 993e95b08c
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
43 changed files with 535 additions and 976 deletions

View File

@ -1,22 +0,0 @@
package org.mariotaku.twidere.util
import org.apache.commons.lang3.reflect.TypeUtils
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mariotaku.microblog.library.twitter.model.CursorTimestampResponse
import org.mariotaku.microblog.library.twitter.model.ResponseList
import org.mariotaku.microblog.library.twitter.model.Status
/**
* Created by mariotaku on 16/2/15.
*/
class TwidereTypeUtilsTest {
@Test
@Throws(Exception::class)
fun testGetSimpleName() {
assertEquals("CursorTimestampResponse", TwidereTypeUtils.toSimpleName(CursorTimestampResponse::class.java))
assertEquals("ResponseList<Status>", TwidereTypeUtils.toSimpleName(TypeUtils.parameterize(ResponseList::class.java, Status::class.java)))
assertEquals("List<List<Object>>", TwidereTypeUtils.toSimpleName(TypeUtils.parameterize(List::class.java, TypeUtils.parameterize(List::class.java, Any::class.java))))
}
}

View File

@ -42,7 +42,7 @@ public class ThemedListPreferenceDialogFragmentCompat extends ThemedPreferenceDi
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
final ListPreference preference = getListPreference();
final String[] entries = TwidereArrayUtils.toStringArray(preference.getEntries());
final CharSequence[] entries = preference.getEntries();
if (entries == null || preference.getEntryValues() == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");

View File

@ -1,93 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.model;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.util.TwidereArrayUtils;
/**
* Created by mariotaku on 15/3/25.
*/
public class StringLongPair {
@NonNull
private final String key;
private long value;
public StringLongPair(@NonNull String key, long value) {
this.key = key;
this.value = value;
}
@NonNull
public String getKey() {
return key;
}
public long getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StringLongPair that = (StringLongPair) o;
return key.equals(that.key);
}
@Override
public int hashCode() {
return key.hashCode();
}
public void setValue(long value) {
this.value = value;
}
@Override
public String toString() {
return key + ":" + value;
}
@NonNull
public static StringLongPair valueOf(@NonNull String s) throws NumberFormatException {
final String[] segs = s.split(":");
if (segs.length != 2) throw new NumberFormatException();
return new StringLongPair(segs[0], Long.parseLong(segs[1]));
}
public static String toString(StringLongPair[] pairs) {
if (pairs == null) return null;
return TwidereArrayUtils.toString(pairs, ';', false);
}
public static StringLongPair[] valuesOf(String s) throws NumberFormatException {
if (s == null) return null;
final String[] segs = s.split(";");
final StringLongPair[] pairs = new StringLongPair[segs.length];
for (int i = 0, j = segs.length; i < j; i++) {
pairs[i] = valueOf(segs[i]);
}
return pairs;
}
}

View File

@ -1,48 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import android.support.annotation.CheckResult;
import java.util.Collection;
/**
* Created by mariotaku on 14/12/7.
*/
public class CollectionUtils {
private CollectionUtils() {
}
@CheckResult
public static <T> String toString(final Collection<T> collection, final char token, final boolean includeSpace) {
final StringBuilder builder = new StringBuilder();
int i = 0;
for (T item : collection) {
final String itemString = String.valueOf(item);
if (i > 0) {
builder.append(includeSpace ? token + " " : token);
}
builder.append(itemString);
i++;
}
return builder.toString();
}
}

View File

@ -1,56 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewParent;
import android.widget.ProgressBar;
import org.mariotaku.twidere.R;
public class MediaLoadingHandler {
private final SparseArray<String> mLoadingUris = new SparseArray<>();
private final int[] mProgressBarIds;
public MediaLoadingHandler() {
this(R.id.media_preview_progress);
}
public MediaLoadingHandler(final int... progressBarIds) {
mProgressBarIds = progressBarIds;
}
public String getLoadingUri(final View view) {
return mLoadingUris.get(System.identityHashCode(view));
}
private ProgressBar findProgressBar(final ViewParent viewParent) {
if (mProgressBarIds == null || !(viewParent instanceof View)) return null;
final View parent = (View) viewParent;
for (final int id : mProgressBarIds) {
final View progress = parent.findViewById(id);
if (progress instanceof ProgressBar) return (ProgressBar) progress;
}
return null;
}
}

View File

@ -69,19 +69,6 @@ public final class TwidereArrayUtils {
}
}
public static String toString(final long[] array, final char token, final boolean include_space) {
final StringBuilder builder = new StringBuilder();
final int length = array.length;
for (int i = 0; i < length; i++) {
final String idString = String.valueOf(array[i]);
if (i > 0) {
builder.append(include_space ? token + " " : token);
}
builder.append(idString);
}
return builder.toString();
}
public static String toString(final Object[] array, final char token, final boolean include_space) {
final StringBuilder builder = new StringBuilder();
final int length = array.length;
@ -106,14 +93,4 @@ public final class TwidereArrayUtils {
return stringArray;
}
public static String[] toStringArray(final Object array) {
return toStringArray(array, 0, Array.getLength(array));
}
public static void offset(long[] array, long offset) {
for (int i = 0; i < array.length; i++) {
array[i] += offset;
}
}
}

View File

@ -1,36 +0,0 @@
package org.mariotaku.twidere.util;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Created by mariotaku on 16/2/15.
*/
public class TwidereTypeUtils {
private TwidereTypeUtils() {
}
public static String toSimpleName(Type type) {
final StringBuilder sb = new StringBuilder();
buildSimpleName(type, sb);
return sb.toString();
}
private static void buildSimpleName(Type type, StringBuilder sb) {
if (type instanceof Class) {
sb.append(((Class) type).getSimpleName());
} else if (type instanceof ParameterizedType) {
buildSimpleName(((ParameterizedType) type).getRawType(), sb);
sb.append("<");
final Type[] args = ((ParameterizedType) type).getActualTypeArguments();
for (int i = 0; i < args.length; i++) {
if (i != 0) {
sb.append(",");
}
buildSimpleName(args[i], sb);
}
sb.append(">");
}
}
}

View File

@ -31,10 +31,6 @@ public class UriUtils {
private UriUtils() {
}
public static Uri appendQueryParameters(final Uri uri, final String key, long value) {
return appendQueryParameters(uri, key, String.valueOf(value));
}
public static Uri appendQueryParameters(final Uri uri, final String key, String value) {
final Uri.Builder builder = uri.buildUpon();
builder.appendQueryParameter(key, value);

View File

@ -493,13 +493,6 @@ public final class Utils implements Constants {
return list.toArray(new String[list.size()]);
}
@NonNull
public static String getNonEmptyString(final SharedPreferences pref, final String key, final String def) {
if (pref == null) return def;
final String val = pref.getString(key, def);
return TextUtils.isEmpty(val) ? def : val;
}
public static String getNormalTwitterProfileImage(final String url) {
return getTwitterProfileImageOfSize(url, "normal");
}

View File

@ -1,161 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.view;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;
import org.mariotaku.chameleon.Chameleon;
import org.mariotaku.chameleon.ChameleonView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.support.TextViewSupport;
import org.mariotaku.twidere.view.iface.IIconActionButton;
/**
* Created by mariotaku on 14/11/20.
*/
public class ActionIconThemedTextView extends AppCompatTextView implements IIconActionButton {
private int mIconWidth, mIconHeight;
@ColorInt
private int mColor;
@ColorInt
private int mDisabledColor;
@ColorInt
private int mActivatedColor;
public ActionIconThemedTextView(Context context) {
super(context);
}
public ActionIconThemedTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
public ActionIconThemedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public void init(Context context, AttributeSet attrs) {
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IconActionButton,
R.attr.cardActionButtonStyle, R.style.Widget_CardActionButton);
mColor = a.getColor(R.styleable.IconActionButton_iabColor, 0);
mDisabledColor = a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0);
mActivatedColor = a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0);
mIconWidth = a.getDimensionPixelSize(R.styleable.IconActionButton_iabIconWidth, 0);
mIconHeight = a.getDimensionPixelSize(R.styleable.IconActionButton_iabIconHeight, 0);
a.recycle();
}
@ColorInt
@Override
public int getDefaultColor() {
if (mColor != 0) return mColor;
final ColorStateList colors = getTextColors();
if (colors != null) return colors.getDefaultColor();
return getCurrentTextColor();
}
@Override
public void setDefaultColor(@ColorInt int color) {
this.mColor = color;
refreshDrawableState();
}
@ColorInt
@Override
public int getActivatedColor() {
if (mActivatedColor != 0) return mActivatedColor;
final ColorStateList colors = getLinkTextColors();
if (colors != null) return colors.getDefaultColor();
return getCurrentTextColor();
}
@Override
public void setActivatedColor(@ColorInt int color) {
this.mActivatedColor = color;
refreshDrawableState();
}
@ColorInt
@Override
public int getDisabledColor() {
if (mDisabledColor != 0) return mDisabledColor;
final ColorStateList colors = getTextColors();
if (colors != null) return colors.getColorForState(new int[0], colors.getDefaultColor());
return getCurrentTextColor();
}
@Override
public void setDisabledColor(@ColorInt int color) {
this.mDisabledColor = color;
refreshDrawableState();
}
@Override
public void refreshDrawableState() {
updateCompoundDrawables();
super.refreshDrawableState();
}
private void updateCompoundDrawables() {
for (Drawable d : TextViewSupport.getCompoundDrawablesRelative(this)) {
if (d == null) continue;
d.mutate();
final int color;
if (isActivated()) {
color = getActivatedColor();
} else if (isEnabled()) {
color = getDefaultColor();
} else {
color = getDisabledColor();
}
if (mIconWidth > 0 && mIconHeight > 0) {
d.setBounds(0, 0, mIconWidth, mIconHeight);
}
d.setColorFilter(color, Mode.SRC_ATOP);
}
}
@Override
public boolean isPostApplyTheme() {
return false;
}
@Nullable
@Override
public Appearance createAppearance(@NonNull Context context, @NonNull AttributeSet attributeSet, @NonNull Chameleon.Theme theme) {
return IIconActionButton.Appearance.create(context, attributeSet, theme);
}
@Override
public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
IIconActionButton.Appearance.apply(this, (Appearance) appearance);
}
}

View File

@ -1,130 +0,0 @@
package org.mariotaku.twidere.view;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.AppCompatImageButton;
import android.util.AttributeSet;
import org.mariotaku.chameleon.Chameleon;
import org.mariotaku.chameleon.ChameleonView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.view.iface.IIconActionButton;
/**
* Created by mariotaku on 14/11/5.
*/
public class IconActionButton extends AppCompatImageButton implements IIconActionButton {
@ColorInt
private int mDefaultColor, mActivatedColor, mDisabledColor;
public IconActionButton(Context context) {
this(context, null);
}
public IconActionButton(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.imageButtonStyle);
}
public IconActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IconActionButton,
R.attr.cardActionButtonStyle, R.style.Widget_CardActionButton);
mDefaultColor = a.getColor(R.styleable.IconActionButton_iabColor, 0);
mActivatedColor = a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0);
mDisabledColor = a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0);
a.recycle();
updateColorFilter();
}
@Override
@ColorInt
public int getDefaultColor() {
if (mDefaultColor == 0) {
// Return inverse color for background tint
ColorStateList color = ViewCompat.getBackgroundTintList(this);
if (color != null) {
final int currentColor = color.getColorForState(getDrawableState(), 0);
return ThemeUtils.getContrastColor(currentColor, Color.BLACK, Color.WHITE);
}
}
return mDefaultColor;
}
@Override
@ColorInt
public int getActivatedColor() {
if (mActivatedColor != 0) return mActivatedColor;
return getDefaultColor();
}
@Override
@ColorInt
public int getDisabledColor() {
if (mDisabledColor != 0) return mDisabledColor;
return getDefaultColor();
}
@Override
public void setDefaultColor(@ColorInt int defaultColor) {
mDefaultColor = defaultColor;
updateColorFilter();
}
@Override
public void setActivatedColor(@ColorInt int activatedColor) {
mActivatedColor = activatedColor;
updateColorFilter();
}
@Override
public void setDisabledColor(@ColorInt int disabledColor) {
mDisabledColor = disabledColor;
updateColorFilter();
}
@Override
public void setActivated(boolean activated) {
super.setActivated(activated);
updateColorFilter();
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
updateColorFilter();
}
private void updateColorFilter() {
if (isActivated()) {
setColorFilter(getActivatedColor());
} else if (isEnabled()) {
setColorFilter(getDefaultColor());
} else {
setColorFilter(getDisabledColor());
}
}
@Override
public boolean isPostApplyTheme() {
return false;
}
@Nullable
@Override
public Appearance createAppearance(@NonNull Context context, @NonNull AttributeSet attributeSet, @NonNull Chameleon.Theme theme) {
return IIconActionButton.Appearance.create(context, attributeSet, theme);
}
@Override
public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
IIconActionButton.Appearance.apply(this, (Appearance) appearance);
}
}

View File

@ -1,126 +0,0 @@
package org.mariotaku.twidere.view;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import org.mariotaku.chameleon.Chameleon;
import org.mariotaku.chameleon.ChameleonView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.view.iface.IIconActionButton;
/**
* Created by mariotaku on 14/11/5.
*/
public class IconActionView extends AppCompatImageView implements IIconActionButton {
@ColorInt
private int mDefaultColor, mActivatedColor, mDisabledColor;
public IconActionView(Context context) {
this(context, null);
}
public IconActionView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IconActionView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (isInEditMode()) return;
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IconActionButton,
R.attr.cardActionButtonStyle, R.style.Widget_CardActionButton);
mDefaultColor = a.getColor(R.styleable.IconActionButton_iabColor, 0);
mActivatedColor = a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0);
mDisabledColor = a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0);
a.recycle();
updateColorFilter();
}
@ColorInt
public int getDefaultColor() {
if (mDefaultColor == 0) {
// Return inverse color for background tint
ColorStateList color = ViewCompat.getBackgroundTintList(this);
if (color != null) {
final int currentColor = color.getColorForState(getDrawableState(), 0);
return ThemeUtils.getContrastColor(currentColor, Color.BLACK, Color.WHITE);
}
}
return mDefaultColor;
}
@ColorInt
public int getActivatedColor() {
if (mActivatedColor != 0) return mActivatedColor;
return getDefaultColor();
}
@ColorInt
public int getDisabledColor() {
if (mDisabledColor != 0) return mDisabledColor;
return getDefaultColor();
}
public void setDefaultColor(@ColorInt int defaultColor) {
mDefaultColor = defaultColor;
updateColorFilter();
}
public void setActivatedColor(@ColorInt int activatedColor) {
mActivatedColor = activatedColor;
updateColorFilter();
}
public void setDisabledColor(@ColorInt int disabledColor) {
mDisabledColor = disabledColor;
updateColorFilter();
}
@Override
public void setActivated(boolean activated) {
super.setActivated(activated);
updateColorFilter();
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
updateColorFilter();
}
private void updateColorFilter() {
if (isActivated()) {
setColorFilter(getActivatedColor());
} else if (isEnabled()) {
setColorFilter(getDefaultColor());
} else {
setColorFilter(getDisabledColor());
}
}
@Override
public boolean isPostApplyTheme() {
return false;
}
@Nullable
@Override
public Appearance createAppearance(@NonNull Context context, @NonNull AttributeSet attributeSet, @NonNull Chameleon.Theme theme) {
return IIconActionButton.Appearance.create(context, attributeSet, theme);
}
@Override
public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
IIconActionButton.Appearance.apply(this, (Appearance) appearance);
}
}

View File

@ -1,85 +0,0 @@
package org.mariotaku.twidere.view.iface;
import android.content.Context;
import android.support.annotation.ColorInt;
import android.util.AttributeSet;
import org.mariotaku.chameleon.Chameleon;
import org.mariotaku.chameleon.ChameleonView;
import org.mariotaku.chameleon.internal.ChameleonTypedArray;
import org.mariotaku.twidere.R;
/**
* Created by mariotaku on 16/3/19.
*/
public interface IIconActionButton extends ChameleonView {
@ColorInt
int getDefaultColor();
@ColorInt
int getActivatedColor();
@ColorInt
int getDisabledColor();
void setDefaultColor(@ColorInt int defaultColor);
void setActivatedColor(@ColorInt int activatedColor);
void setDisabledColor(@ColorInt int disabledColor);
class Appearance implements ChameleonView.Appearance {
@ColorInt
private int defaultColor, activatedColor, disabledColor;
public int getActivatedColor() {
return activatedColor;
}
public void setActivatedColor(int activatedColor) {
this.activatedColor = activatedColor;
}
public int getDefaultColor() {
return defaultColor;
}
public void setDefaultColor(int defaultColor) {
this.defaultColor = defaultColor;
}
public int getDisabledColor() {
return disabledColor;
}
public void setDisabledColor(int disabledColor) {
this.disabledColor = disabledColor;
}
public static Appearance create(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
Appearance appearance = new Appearance();
ChameleonTypedArray a = ChameleonTypedArray.obtain(context, attributeSet, R.styleable.IconActionButton, theme);
appearance.setDefaultColor(a.getColor(R.styleable.IconActionButton_iabColor, 0, false));
appearance.setActivatedColor(a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0, false));
appearance.setDisabledColor(a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0, false));
a.recycle();
return appearance;
}
public static void apply(IIconActionButton view, Appearance appearance) {
final int defaultColor = appearance.getDefaultColor();
if (defaultColor != 0) {
view.setDefaultColor(defaultColor);
}
final int activatedColor = appearance.getActivatedColor();
if (activatedColor != 0) {
view.setActivatedColor(activatedColor);
}
final int disabledColor = appearance.getDisabledColor();
if (disabledColor != 0) {
view.setDisabledColor(disabledColor);
}
}
}
}

View File

@ -75,6 +75,7 @@ import org.mariotaku.twidere.constant.chromeCustomTabKey
import org.mariotaku.twidere.constant.defaultAPIConfigKey
import org.mariotaku.twidere.constant.randomizeAccountNameKey
import org.mariotaku.twidere.extension.applyTheme
import org.mariotaku.twidere.extension.getNonEmptyString
import org.mariotaku.twidere.extension.model.getColor
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.extension.model.official
@ -454,12 +455,12 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
private fun setDefaultAPI() {
val apiLastChange = preferences.getLong(KEY_API_LAST_CHANGE, apiChangeTimestamp)
val defaultApiChanged = apiLastChange != apiChangeTimestamp
val apiUrlFormat = Utils.getNonEmptyString(preferences, KEY_API_URL_FORMAT, DEFAULT_TWITTER_API_URL_FORMAT)
val apiUrlFormat = preferences.getNonEmptyString(KEY_API_URL_FORMAT, DEFAULT_TWITTER_API_URL_FORMAT)
val authType = preferences.getString(KEY_CREDENTIALS_TYPE, Credentials.Type.OAUTH)
val sameOAuthSigningUrl = preferences.getBoolean(KEY_SAME_OAUTH_SIGNING_URL, false)
val noVersionSuffix = preferences.getBoolean(KEY_NO_VERSION_SUFFIX, false)
val consumerKey = Utils.getNonEmptyString(preferences, KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY)
val consumerSecret = Utils.getNonEmptyString(preferences, KEY_CONSUMER_SECRET, TWITTER_CONSUMER_SECRET)
val consumerKey = preferences.getNonEmptyString(KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY)
val consumerSecret = preferences.getNonEmptyString(KEY_CONSUMER_SECRET, TWITTER_CONSUMER_SECRET)
if (TextUtils.isEmpty(apiConfig.apiUrlFormat) || defaultApiChanged) {
apiConfig.apiUrlFormat = apiUrlFormat
}

View File

@ -48,7 +48,6 @@ class DraftsAdapter(
@Inject
lateinit var preferences: SharedPreferencesWrapper
private val mediaLoadingHandler = MediaLoadingHandler(R.id.media_preview_progress)
private val mediaPreviewStyle: Int
var textSize: Float = 0f
@ -78,7 +77,7 @@ class DraftsAdapter(
val media = ParcelableMediaUtils.fromMediaUpdates(draft.media)
holder.mediaPreviewContainer.visibility = View.VISIBLE
holder.mediaPreviewContainer.displayMedia(requestManager = requestManager,
media = media, loadingHandler = mediaLoadingHandler)
media = media)
}
Draft.Action.FAVORITE, Draft.Action.RETWEET -> {
val extras = draft.action_extras as? StatusObjectExtras

View File

@ -36,7 +36,6 @@ class DummyItemAdapter(
override lateinit var userColorNameManager: UserColorNameManager
@Inject
override lateinit var bidiFormatter: BidiFormatter
override val mediaLoadingHandler: MediaLoadingHandler = MediaLoadingHandler(R.id.media_preview_progress)
override var profileImageStyle: Int = 0
override var mediaPreviewStyle: Int = 0

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import com.bumptech.glide.RequestManager
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
import org.mariotaku.twidere.view.holder.StatusViewHolder
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
@ -17,9 +16,6 @@ class ListParcelableStatusesAdapter(
requestManager: RequestManager
) : ParcelableStatusesAdapter(context, requestManager) {
override val progressViewIds: IntArray
get() = intArrayOf(R.id.media_preview_progress)
override fun onCreateStatusViewHolder(parent: ViewGroup): IStatusViewHolder {
return createStatusViewHolder(this, inflater, parent)
}

View File

@ -37,7 +37,6 @@ import org.mariotaku.twidere.extension.model.timestamp
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.ParcelableMessage.MessageType
import org.mariotaku.twidere.util.DirectMessageOnLinkClickHandler
import org.mariotaku.twidere.util.MediaLoadingHandler
import org.mariotaku.twidere.util.TwidereLinkify
import org.mariotaku.twidere.view.CardMediaContainer.OnMediaClickListener
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder
@ -60,7 +59,6 @@ class MessagesConversationAdapter(
val linkHighlightingStyle: Int = preferences[linkHighlightOptionKey]
val nameFirst: Boolean = preferences[nameFirstKey]
val linkify: TwidereLinkify = TwidereLinkify(DirectMessageOnLinkClickHandler(context, null, preferences))
val mediaLoadingHandler: MediaLoadingHandler = MediaLoadingHandler()
val mediaClickListener: OnMediaClickListener = object : OnMediaClickListener {
override fun onMediaClick(view: View, media: ParcelableMedia, accountKey: UserKey?, id: Long) {
listener?.onMediaClick(id.toInt(), media, accountKey)

View File

@ -44,7 +44,6 @@ import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
import org.mariotaku.twidere.model.util.getActivityStatus
import org.mariotaku.twidere.util.IntentUtils
import org.mariotaku.twidere.util.MediaLoadingHandler
import org.mariotaku.twidere.util.OnLinkClickHandler
import org.mariotaku.twidere.util.TwidereLinkify
import org.mariotaku.twidere.view.holder.*
@ -60,8 +59,6 @@ class ParcelableActivitiesAdapter(
requestManager: RequestManager
) : LoadMoreSupportAdapter<RecyclerView.ViewHolder>(context, requestManager), IActivitiesAdapter<List<ParcelableActivity>> {
override val mediaLoadingHandler = MediaLoadingHandler(R.id.media_preview_progress)
private val inflater = LayoutInflater.from(context)
private val twidereLinkify = TwidereLinkify(OnLinkClickHandler(context, null, preferences))
private val statusAdapterDelegate = DummyItemAdapter(context, twidereLinkify, this, requestManager)
@ -229,8 +226,7 @@ class ParcelableActivitiesAdapter(
ITEM_VIEW_TYPE_STATUS -> {
val status = getActivity(position)?.getActivityStatus() ?: return
val statusViewHolder = holder as IStatusViewHolder
statusViewHolder.displayStatus(status = status, displayInReplyTo = true,
displayExtraType = true)
statusViewHolder.displayStatus(status = status, displayInReplyTo = true)
}
ITEM_VIEW_TYPE_TITLE_SUMMARY -> {
bindTitleSummaryViewHolder(holder as ActivityTitleSummaryViewHolder, position)

View File

@ -42,7 +42,6 @@ import org.mariotaku.twidere.annotation.PreviewStyle
import org.mariotaku.twidere.constant.*
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_DISPLAY_SENSITIVE_CONTENTS
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.util.MediaLoadingHandler
import org.mariotaku.twidere.util.StatusAdapterLinkClickHandler
import org.mariotaku.twidere.util.TwidereLinkify
import org.mariotaku.twidere.util.Utils
@ -63,7 +62,6 @@ abstract class ParcelableStatusesAdapter(
protected val inflater: LayoutInflater = LayoutInflater.from(context)
override final val mediaLoadingHandler: MediaLoadingHandler
final override val twidereLinkify: TwidereLinkify
@PreviewStyle
final override val mediaPreviewStyle: Int = preferences[mediaPreviewStyleKey]
@ -117,8 +115,6 @@ abstract class ParcelableStatusesAdapter(
override val itemCounts = ItemCounts(4)
protected abstract val progressViewIds: IntArray
val statusStartIndex: Int
get() = getItemStartPosition(ITEM_INDEX_STATUS)
@ -137,7 +133,6 @@ abstract class ParcelableStatusesAdapter(
}
init {
mediaLoadingHandler = MediaLoadingHandler(*progressViewIds)
val handler = StatusAdapterLinkClickHandler<List<ParcelableStatus>>(context, preferences)
twidereLinkify = TwidereLinkify(handler)
handler.setAdapter(this)

View File

@ -33,9 +33,6 @@ class StaggeredGridParcelableStatusesAdapter(
requestManager: RequestManager
) : ParcelableStatusesAdapter(context, requestManager) {
override val progressViewIds: IntArray
get() = intArrayOf(R.id.mediaImageProgress)
override fun onCreateStatusViewHolder(parent: ViewGroup): IStatusViewHolder {
val view = inflater.inflate(R.layout.adapter_item_media_status, parent, false)
val holder = MediaStatusViewHolder(this, view)

View File

@ -20,7 +20,6 @@
package org.mariotaku.twidere.adapter.iface
import org.mariotaku.twidere.model.ParcelableActivity
import org.mariotaku.twidere.util.MediaLoadingHandler
import org.mariotaku.twidere.view.holder.ActivityTitleSummaryViewHolder
/**
@ -32,8 +31,6 @@ interface IActivitiesAdapter<in Data> : IContentAdapter, IGapSupportedAdapter {
val mediaPreviewStyle: Int
val mediaLoadingHandler: MediaLoadingHandler
val mediaPreviewEnabled: Boolean
val activityEventListener: ActivityEventListener?

View File

@ -3,9 +3,7 @@ package org.mariotaku.twidere.adapter.iface
import org.mariotaku.twidere.annotation.PreviewStyle
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.MediaLoadingHandler
import org.mariotaku.twidere.util.TwidereLinkify
import org.mariotaku.twidere.view.CardMediaContainer
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
/**
@ -37,8 +35,6 @@ interface IStatusesAdapter<in Data> : IContentAdapter, IGapSupportedAdapter {
val useStarsForLikes: Boolean
val mediaLoadingHandler: MediaLoadingHandler
val statusClickListener: IStatusViewHolder.StatusClickListener?
fun isCardActionsShown(position: Int): Boolean

View File

@ -1,12 +1,10 @@
package org.mariotaku.twidere.extension
import android.content.SharedPreferences
import android.text.TextUtils
/**
* Created by mariotaku on 16/8/25.
*/
fun SharedPreferences.getNonEmptyString(key: String, def: String): String {
val v = getString(key, def)
return if (TextUtils.isEmpty(v)) def else v
return getString(key, def)?.takeUnless(String::isEmpty) ?: def
}

View File

@ -94,7 +94,7 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
val adapter = DummyItemAdapter(context, requestManager = Glide.with(this))
adapter.setShouldShowAccountsColor(true)
val holder = StatusViewHolder(adapter, itemContent)
holder.displayStatus(status = status, displayInReplyTo = false, displayExtraType = true)
holder.displayStatus(status = status, displayInReplyTo = false)
textCountView.maxLength = details.textLimit

View File

@ -1020,8 +1020,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
itemView.mediaPreview.visibility = View.VISIBLE
itemView.mediaPreviewLoad.visibility = View.GONE
itemView.mediaPreview.displayMedia(adapter.requestManager, media = media,
accountId = status.account_key, mediaClickListener = adapter.fragment,
loadingHandler = adapter.mediaLoadingHandler)
accountId = status.account_key, mediaClickListener = adapter.fragment)
} else {
itemView.mediaPreviewContainer.visibility = View.VISIBLE
itemView.mediaPreview.visibility = View.GONE
@ -1487,7 +1486,6 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
val fragment: StatusFragment
) : LoadMoreSupportAdapter<ViewHolder>(fragment.context, Glide.with(fragment)), IStatusesAdapter<List<ParcelableStatus>> {
private val inflater: LayoutInflater
override val mediaLoadingHandler = MediaLoadingHandler(R.id.media_preview_progress)
override val twidereLinkify: TwidereLinkify
override var statusClickListener: StatusClickListener? = null

View File

@ -44,14 +44,12 @@ import org.mariotaku.twidere.model.util.ParcelableStatusUtils
import org.mariotaku.twidere.task.twitter.GetStatusesTask
import org.mariotaku.twidere.util.DebugLog
import org.mariotaku.twidere.util.SharedPreferencesWrapper
import org.mariotaku.twidere.util.TwidereArrayUtils
import org.mariotaku.twidere.util.UserColorNameManager
import org.mariotaku.twidere.util.cache.JsonCache
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import java.io.IOException
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicReference
import javax.inject.Inject
@ -218,10 +216,7 @@ abstract class MicroBlogAPIStatusesLoader(
}
private val serializationKey: String?
get() {
if (savedStatusesArgs == null) return null
return TwidereArrayUtils.toString(savedStatusesArgs, '_', false)
}
get() = savedStatusesArgs?.joinToString("_")
private fun saveCachedData(data: List<ParcelableStatus>?) {
val key = serializationKey
@ -239,9 +234,4 @@ abstract class MicroBlogAPIStatusesLoader(
}
companion object {
private val pool = Executors.newSingleThreadExecutor()
}
}

View File

@ -19,18 +19,33 @@
package org.mariotaku.twidere.util.cache
import org.mariotaku.twidere.model.ParcelableStatus
import com.bluelinelabs.logansquare.LoganSquare
import com.bumptech.glide.disklrucache.DiskLruCache
import org.mariotaku.twidere.BuildConfig
import java.io.File
import java.io.IOException
/**
* Created by mariotaku on 2017/3/1.
*/
class JsonCache {
fun <T> getList(key: String, cls: Class<T>): List<T>? {
return emptyList()
class JsonCache(val cacheDir: File) {
private val cache = try {
DiskLruCache.open(cacheDir, BuildConfig.VERSION_CODE, 1, 100 * 1048576)
} catch (e: IOException) {
null
}
fun <T> saveList(key: String, list: List<T>, cls: Class<ParcelableStatus>) {
fun <T> getList(key: String, cls: Class<T>): List<T>? {
return cache?.get(key)?.getFile(0)?.inputStream()?.use {
LoganSquare.parseList(it, cls)
}
}
fun <T> saveList(key: String, list: List<T>, cls: Class<T>) {
cache?.get(key)?.getFile(0)?.outputStream()?.use {
LoganSquare.serialize(list, it, cls)
}
}
}

View File

@ -314,7 +314,7 @@ class ApplicationModule(private val application: Application) {
@Provides
@Singleton
fun jsonCache(): JsonCache {
return JsonCache()
return JsonCache(getCacheDir("json"))
}
@Provides

View File

@ -0,0 +1,129 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.view
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.PorterDuff.Mode
import android.support.annotation.ColorInt
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSet
import org.mariotaku.chameleon.Chameleon
import org.mariotaku.chameleon.ChameleonView
import org.mariotaku.twidere.R
import org.mariotaku.twidere.util.support.TextViewSupport
import org.mariotaku.twidere.view.iface.IIconActionButton
/**
* Created by mariotaku on 14/11/20.
*/
class ActionIconThemedTextView(
context: Context, attrs: AttributeSet? = null
) : AppCompatTextView(context, attrs, android.R.attr.textViewStyle), IIconActionButton {
private var iconWidth: Int = 0
private var iconHeight: Int = 0
override var defaultColor: Int = 0
@ColorInt get() {
if (field != 0) return field
val colors = textColors
if (colors != null) return colors.defaultColor
return currentTextColor
}
set(value) {
field = value
refreshDrawableState()
}
override var disabledColor: Int = 0
@ColorInt get() {
if (field != 0) return field
val colors = textColors
if (colors != null) return colors.getColorForState(IntArray(0), colors.defaultColor)
return currentTextColor
}
@ColorInt set(value) {
field = value
refreshDrawableState()
}
override var activatedColor: Int = 0
@ColorInt get() {
if (field != 0) return field
val colors = linkTextColors
if (colors != null) return colors.defaultColor
return currentTextColor
}
@ColorInt set(value) {
field = value
refreshDrawableState()
}
init {
@SuppressLint("CustomViewStyleable")
val a = context.obtainStyledAttributes(attrs, R.styleable.IconActionButton,
R.attr.cardActionButtonStyle, R.style.Widget_CardActionButton)
defaultColor = a.getColor(R.styleable.IconActionButton_iabColor, 0)
disabledColor = a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0)
activatedColor = a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0)
iconWidth = a.getDimensionPixelSize(R.styleable.IconActionButton_iabIconWidth, 0)
iconHeight = a.getDimensionPixelSize(R.styleable.IconActionButton_iabIconHeight, 0)
a.recycle()
}
override fun refreshDrawableState() {
updateCompoundDrawables()
super.refreshDrawableState()
}
private fun updateCompoundDrawables() {
for (d in TextViewSupport.getCompoundDrawablesRelative(this)) {
if (d == null) continue
d.mutate()
val color: Int
if (isActivated) {
color = activatedColor
} else if (isEnabled) {
color = defaultColor
} else {
color = disabledColor
}
if (iconWidth > 0 && iconHeight > 0) {
d.setBounds(0, 0, iconWidth, iconHeight)
}
d.setColorFilter(color, Mode.SRC_ATOP)
}
}
override fun isPostApplyTheme(): Boolean {
return false
}
override fun createAppearance(context: Context, attributeSet: AttributeSet, theme: Chameleon.Theme): IIconActionButton.Appearance? {
return IIconActionButton.Appearance.create(context, attributeSet, theme)
}
override fun applyAppearance(appearance: ChameleonView.Appearance) {
IIconActionButton.Appearance.apply(this, appearance as IIconActionButton.Appearance)
}
}

View File

@ -32,7 +32,6 @@ import org.mariotaku.twidere.extension.model.aspect_ratio
import org.mariotaku.twidere.model.ParcelableMedia
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
import org.mariotaku.twidere.util.MediaLoadingHandler
import java.lang.ref.WeakReference
/**
@ -71,7 +70,7 @@ class CardMediaContainer(context: Context, attrs: AttributeSet? = null) : ViewGr
fun displayMedia(requestManager: RequestManager, media: Array<ParcelableMedia>?, accountId: UserKey? = null,
extraId: Long = -1, withCredentials: Boolean = false,
mediaClickListener: OnMediaClickListener? = null, loadingHandler: MediaLoadingHandler? = null) {
mediaClickListener: OnMediaClickListener? = null) {
if (media == null || style == PreviewStyle.NONE) {
for (i in 0 until childCount) {
val child = getChildAt(i)

View File

@ -0,0 +1,102 @@
package org.mariotaku.twidere.view
import android.content.Context
import android.graphics.Color
import android.support.annotation.ColorInt
import android.support.v4.view.ViewCompat
import android.support.v7.widget.AppCompatImageButton
import android.util.AttributeSet
import org.mariotaku.chameleon.Chameleon
import org.mariotaku.chameleon.ChameleonView
import org.mariotaku.twidere.R
import org.mariotaku.twidere.util.ThemeUtils
import org.mariotaku.twidere.view.iface.IIconActionButton
/**
* Created by mariotaku on 14/11/5.
*/
class IconActionButton(
context: Context, attrs: AttributeSet? = null
) : AppCompatImageButton(context, attrs, R.attr.imageButtonStyle), IIconActionButton {
override var defaultColor: Int = 0
@ColorInt
get() {
if (field == 0) {
val color = ViewCompat.getBackgroundTintList(this)
if (color != null) {
val currentColor = color.getColorForState(drawableState, 0)
return ThemeUtils.getContrastColor(currentColor, Color.BLACK, Color.WHITE)
}
}
return field
}
set(@ColorInt defaultColor) {
field = defaultColor
updateColorFilter()
}
override var activatedColor: Int = 0
@ColorInt
get() {
if (field != 0) return field
return defaultColor
}
set(@ColorInt activatedColor) {
field = activatedColor
updateColorFilter()
}
override var disabledColor: Int = 0
@ColorInt
get() {
if (field != 0) return field
return defaultColor
}
set(@ColorInt disabledColor) {
field = disabledColor
updateColorFilter()
}
init {
val a = context.obtainStyledAttributes(attrs, R.styleable.IconActionButton,
R.attr.cardActionButtonStyle, R.style.Widget_CardActionButton)
defaultColor = a.getColor(R.styleable.IconActionButton_iabColor, 0)
activatedColor = a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0)
disabledColor = a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0)
a.recycle()
updateColorFilter()
}
override fun setActivated(activated: Boolean) {
super.setActivated(activated)
updateColorFilter()
}
override fun setEnabled(enabled: Boolean) {
super.setEnabled(enabled)
updateColorFilter()
}
private fun updateColorFilter() {
if (isActivated) {
setColorFilter(activatedColor)
} else if (isEnabled) {
setColorFilter(defaultColor)
} else {
setColorFilter(disabledColor)
}
}
override fun isPostApplyTheme(): Boolean {
return false
}
override fun createAppearance(context: Context, attributeSet: AttributeSet, theme: Chameleon.Theme): IIconActionButton.Appearance? {
return IIconActionButton.Appearance.create(context, attributeSet, theme)
}
override fun applyAppearance(appearance: ChameleonView.Appearance) {
IIconActionButton.Appearance.apply(this, appearance as IIconActionButton.Appearance)
}
}

View File

@ -0,0 +1,104 @@
package org.mariotaku.twidere.view
import android.content.Context
import android.graphics.Color
import android.support.annotation.ColorInt
import android.support.v4.view.ViewCompat
import android.support.v7.widget.AppCompatImageView
import android.util.AttributeSet
import org.mariotaku.chameleon.Chameleon
import org.mariotaku.chameleon.ChameleonView
import org.mariotaku.twidere.R
import org.mariotaku.twidere.util.ThemeUtils
import org.mariotaku.twidere.view.iface.IIconActionButton
/**
* Created by mariotaku on 14/11/5.
*/
open class IconActionView(
context: Context, attrs: AttributeSet? = null
) : AppCompatImageView(context, attrs), IIconActionButton {
override final var defaultColor: Int = 0
@ColorInt
get() {
if (field != 0) return field
val color = ViewCompat.getBackgroundTintList(this)
if (color != null) {
val currentColor = color.getColorForState(drawableState, 0)
return ThemeUtils.getContrastColor(currentColor, Color.BLACK, Color.WHITE)
}
return field
}
set(@ColorInt defaultColor) {
field = defaultColor
updateColorFilter()
}
override final var activatedColor: Int = 0
@ColorInt
get() {
if (field != 0) return field
return defaultColor
}
set(@ColorInt value) {
field = value
updateColorFilter()
}
override final var disabledColor: Int = 0
@ColorInt
get() {
if (field != 0) return field
return defaultColor
}
set(@ColorInt value) {
field = value
updateColorFilter()
}
init {
if (!isInEditMode) {
val a = context.obtainStyledAttributes(attrs, R.styleable.IconActionButton,
R.attr.cardActionButtonStyle, R.style.Widget_CardActionButton)
defaultColor = a.getColor(R.styleable.IconActionButton_iabColor, 0)
activatedColor = a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0)
disabledColor = a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0)
a.recycle()
}
updateColorFilter()
}
override fun setActivated(activated: Boolean) {
super.setActivated(activated)
updateColorFilter()
}
override fun setEnabled(enabled: Boolean) {
super.setEnabled(enabled)
updateColorFilter()
}
private fun updateColorFilter() {
if (isActivated) {
setColorFilter(activatedColor)
} else if (isEnabled) {
setColorFilter(defaultColor)
} else {
setColorFilter(disabledColor)
}
}
override fun isPostApplyTheme(): Boolean {
return false
}
override fun createAppearance(context: Context, attributeSet: AttributeSet, theme: Chameleon.Theme): IIconActionButton.Appearance? {
return IIconActionButton.Appearance.create(context, attributeSet, theme)
}
override fun applyAppearance(appearance: ChameleonView.Appearance) {
IIconActionButton.Appearance.apply(this, appearance as IIconActionButton.Appearance)
}
}

View File

@ -70,7 +70,7 @@ class NameView(context: Context, attrs: AttributeSet? = null) : FixedTextView(co
secondaryTextStyle = StyleSpan(a.getInt(R.styleable.NameView_nv_secondaryTextStyle, 0))
a.recycle()
nameFirst = true
if (isInEditMode) {
if (isInEditMode && text.isNullOrEmpty()) {
name = "Name"
screenName = "@screenname"
updateText()

View File

@ -54,7 +54,7 @@ class MediaStatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView:
}
override fun displayStatus(status: ParcelableStatus, displayInReplyTo: Boolean,
displayExtraType: Boolean, displayPinned: Boolean) {
displayPinned: Boolean) {
val media = status.media ?: return
if (media.isEmpty()) return
val firstMedia = media[0]

View File

@ -1,12 +1,12 @@
package org.mariotaku.twidere.view.holder
import android.support.v4.content.ContextCompat
import android.support.v4.widget.TextViewCompat
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.ViewHolder
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.view.View
import android.view.View.OnClickListener
@ -28,7 +28,6 @@ import org.mariotaku.twidere.model.ParcelableLocation
import org.mariotaku.twidere.model.ParcelableMedia
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableLocationUtils
import org.mariotaku.twidere.task.CreateFavoriteTask
import org.mariotaku.twidere.task.DestroyFavoriteTask
import org.mariotaku.twidere.task.RetweetStatusTask
@ -58,7 +57,6 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
private val itemMenu by lazy { itemView.itemMenu }
private val statusInfoLabel by lazy { itemView.statusInfoLabel }
private val statusInfoIcon by lazy { itemView.statusInfoIcon }
private val extraTypeView by lazy { itemView.extraType }
private val quotedNameView by lazy { itemView.quotedName }
private val timeView by lazy { itemView.time }
private val replyCountView by lazy { itemView.replyCount }
@ -73,8 +71,6 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
private val favoriteIcon by lazy { itemView.favoriteIcon }
private val retweetIcon by lazy { itemView.retweetIcon }
private val favoriteCountView by lazy { itemView.favoriteCount }
private val mediaLabelTextView by lazy { itemView.mediaLabelText }
private val quotedMediaLabelTextView by lazy { itemView.quotedMediaLabelText }
private val replyButton by lazy { itemView.reply }
private val retweetButton by lazy { itemView.retweet }
private val favoriteButton by lazy { itemView.favorite }
@ -131,11 +127,10 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
quotedMediaPreview.visibility = View.GONE
quotedMediaLabel.visibility = View.GONE
mediaPreview.displayMedia(R.drawable.featured_graphics)
extraTypeView.setImageResource(R.drawable.ic_action_gallery)
}
override fun displayStatus(status: ParcelableStatus, displayInReplyTo: Boolean,
displayExtraType: Boolean, displayPinned: Boolean) {
displayPinned: Boolean) {
val context = itemView.context
val requestManager = adapter.requestManager
@ -336,7 +331,7 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
mediaPreview.displayMedia(requestManager = requestManager,
media = status.media, accountId = status.account_key,
mediaClickListener = this, loadingHandler = adapter.mediaLoadingHandler)
mediaClickListener = this)
}
} else {
// No media, hide all related views
@ -414,12 +409,6 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
favoriteCountView.text = null
favoriteCountView.visibility = View.GONE
}
if (displayExtraType) {
displayExtraTypeIcon(status.card_name, status.media, status.location,
status.place_full_name, status.is_possibly_sensitive)
} else {
extraTypeView.visibility = View.GONE
}
nameView.updateText(formatter)
quotedNameView.updateText(formatter)
@ -444,7 +433,7 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
quotedMediaPreview.displayMedia(requestManager = requestManager,
media = status.quoted_media, accountId = status.account_key,
mediaClickListener = this, loadingHandler = adapter.mediaLoadingHandler)
mediaClickListener = this)
}
} else {
// No media, hide all related views
@ -494,7 +483,8 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
timeView.textSize = textSize * 0.85f
statusInfoLabel.textSize = textSize * 0.75f
mediaLabelTextView.textSize = textSize * 0.95f
mediaLabel.textSize = textSize * 0.95f
quotedMediaLabel.textSize = textSize * 0.95f
replyCountView.textSize = textSize
retweetCountView.textSize = textSize
@ -537,11 +527,11 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
nameView.applyFontFamily(adapter.lightFont)
timeView.applyFontFamily(adapter.lightFont)
textView.applyFontFamily(adapter.lightFont)
mediaLabelTextView.applyFontFamily(adapter.lightFont)
mediaLabel.applyFontFamily(adapter.lightFont)
quotedNameView.applyFontFamily(adapter.lightFont)
quotedTextView.applyFontFamily(adapter.lightFont)
quotedMediaLabelTextView.applyFontFamily(adapter.lightFont)
quotedMediaLabel.applyFontFamily(adapter.lightFont)
}
override fun playLikeAnimation(listener: LikeAnimationDrawable.OnLikedListener) {
@ -572,28 +562,13 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
private fun displayExtraTypeIcon(cardName: String?, media: Array<ParcelableMedia?>?,
location: ParcelableLocation?, placeFullName: String?,
sensitive: Boolean) {
if (TwitterCardUtils.CARD_NAME_AUDIO == cardName) {
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_music)
extraTypeView.visibility = View.VISIBLE
} else if (TwitterCardUtils.CARD_NAME_ANIMATED_GIF == cardName) {
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_movie)
extraTypeView.visibility = View.VISIBLE
} else if (TwitterCardUtils.CARD_NAME_PLAYER == cardName) {
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_play_circle)
extraTypeView.visibility = View.VISIBLE
} else if (media?.isNotEmpty() ?: false) {
if (hasVideo(media)) {
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_movie)
} else {
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_gallery)
}
extraTypeView.visibility = View.VISIBLE
} else if (ParcelableLocationUtils.isValidLocation(location) || !TextUtils.isEmpty(placeFullName)) {
extraTypeView.setImageResource(R.drawable.ic_action_location)
extraTypeView.visibility = View.VISIBLE
val icon = if (sensitive) {
R.drawable.ic_label_warning
} else {
extraTypeView.visibility = View.GONE
R.drawable.ic_label_gallery
}
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(mediaLabel, icon, 0, 0, 0)
mediaLabel.refreshDrawableState()
}
private fun hasVideo(media: Array<ParcelableMedia?>?): Boolean {

View File

@ -35,7 +35,7 @@ import org.mariotaku.twidere.view.CardMediaContainer
interface IStatusViewHolder : CardMediaContainer.OnMediaClickListener {
fun displayStatus(status: ParcelableStatus, displayInReplyTo: Boolean = true,
displayExtraType: Boolean = true, displayPinned: Boolean = false)
displayPinned: Boolean = false)
val profileImageView: ImageView?

View File

@ -109,8 +109,8 @@ class MessageViewHolder(itemView: View, adapter: MessagesConversationAdapter) :
} else {
mediaPreview.visibility = View.VISIBLE
mediaPreview.displayMedia(adapter.requestManager, message.media, message.account_key,
withCredentials = true, loadingHandler = adapter.mediaLoadingHandler,
mediaClickListener = adapter.mediaClickListener, extraId = layoutPosition.toLong())
extraId = layoutPosition.toLong(), withCredentials = true,
mediaClickListener = adapter.mediaClickListener)
}
}

View File

@ -0,0 +1,60 @@
package org.mariotaku.twidere.view.iface
import android.content.Context
import android.support.annotation.ColorInt
import android.util.AttributeSet
import org.mariotaku.chameleon.Chameleon
import org.mariotaku.chameleon.ChameleonView
import org.mariotaku.chameleon.internal.ChameleonTypedArray
import org.mariotaku.twidere.R
/**
* Created by mariotaku on 16/3/19.
*/
interface IIconActionButton : ChameleonView {
var defaultColor: Int
@ColorInt get @ColorInt set
var activatedColor: Int
@ColorInt get @ColorInt set
var disabledColor: Int
@ColorInt get @ColorInt set
class Appearance : ChameleonView.Appearance {
var defaultColor: Int = 0
@ColorInt get @ColorInt set
var activatedColor: Int = 0
@ColorInt get @ColorInt set
var disabledColor: Int = 0
@ColorInt get @ColorInt set
companion object {
fun create(context: Context, attributeSet: AttributeSet, theme: Chameleon.Theme): Appearance {
val appearance = Appearance()
val a = ChameleonTypedArray.obtain(context, attributeSet, R.styleable.IconActionButton, theme)
appearance.defaultColor = a.getColor(R.styleable.IconActionButton_iabColor, 0, false)
appearance.activatedColor = a.getColor(R.styleable.IconActionButton_iabActivatedColor, 0, false)
appearance.disabledColor = a.getColor(R.styleable.IconActionButton_iabDisabledColor, 0, false)
a.recycle()
return appearance
}
fun apply(view: IIconActionButton, appearance: Appearance) {
val defaultColor = appearance.defaultColor
if (defaultColor != 0) {
view.defaultColor = defaultColor
}
val activatedColor = appearance.activatedColor
if (activatedColor != 0) {
view.activatedColor = activatedColor
}
val disabledColor = appearance.disabledColor
if (disabledColor != 0) {
view.disabledColor = disabledColor
}
}
}
}
}

View File

@ -111,52 +111,40 @@
android:layout_height="wrap_content"
android:layout_below="@+id/statusContentUpperSpace"
android:layout_toEndOf="@+id/profileImage"
android:layout_toRightOf="@+id/profileImage"
android:orientation="vertical">
android:layout_toRightOf="@+id/profileImage">
<LinearLayout
android:id="@+id/profileContainer"
android:layout_width="match_parent"
<org.mariotaku.twidere.view.NameView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|start"
android:orientation="horizontal">
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/time"
android:layout_toStartOf="@+id/time"
android:ellipsize="end"
android:maxLines="1"
app:nv_primaryTextColor="?android:textColorPrimary"
app:nv_primaryTextStyle="bold"
app:nv_secondaryTextColor="?android:textColorSecondary"/>
<org.mariotaku.twidere.view.NameView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
app:nv_primaryTextColor="?android:textColorPrimary"
app:nv_primaryTextStyle="bold"
app:nv_secondaryTextColor="?android:textColorSecondary"/>
<org.mariotaku.twidere.view.ShortTimeView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:textAppearance="?android:textAppearanceSmall"
tools:text="42 mins ago"
tools:textSize="@dimen/text_size_extra_small"/>
<org.mariotaku.twidere.view.IconActionView
android:id="@+id/extraType"
android:layout_width="@dimen/element_size_small"
android:layout_height="@dimen/element_size_small"
android:layout_weight="0"
android:color="?android:textColorSecondary"
tools:src="@drawable/ic_action_gallery"
tools:tint="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.ShortTimeView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/name"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:textAppearance="?android:textAppearanceSmall"
tools:text="42 mins ago"
tools:textSize="@dimen/text_size_extra_small"/>
<org.mariotaku.twidere.view.TimelineContentTextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/profileContainer"
android:layout_alignStart="@+id/profileContainer"
android:layout_below="@+id/profileContainer"
android:layout_alignLeft="@+id/name"
android:layout_alignStart="@+id/name"
android:layout_below="@+id/name"
android:paddingTop="@dimen/element_spacing_small"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
@ -164,7 +152,7 @@
tools:text="@string/sample_status_text"
tools:visibility="visible"/>
<LinearLayout
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/mediaLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -175,28 +163,14 @@
android:layout_below="@+id/text"
android:layout_marginTop="@dimen/element_spacing_xsmall"
android:background="?selectableItemBackground"
android:drawableLeft="@drawable/ic_label_gallery"
android:drawableStart="@drawable/ic_label_gallery"
android:gravity="center_vertical"
android:orientation="horizontal">
<org.mariotaku.twidere.view.IconActionView
android:layout_width="@dimen/element_size_small"
android:layout_height="@dimen/element_size_small"
android:layout_weight="0"
android:color="?android:textColorSecondary"
android:scaleType="centerInside"
android:src="@drawable/ic_action_gallery"
tools:tint="?android:textColorSecondary"/>
<org.mariotaku.twidere.view.FixedTextView
android:id="@+id/mediaLabelText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/media"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold"/>
</LinearLayout>
android:minHeight="@dimen/element_size_small"
android:text="@string/media"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold"
app:iabColor="?android:textColorSecondary"/>
<org.mariotaku.twidere.view.CardMediaContainer
android:id="@+id/mediaPreview"
@ -278,7 +252,7 @@
tools:text="@string/sample_status_text"
tools:visibility="visible"/>
<LinearLayout
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/quotedMediaLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -288,29 +262,14 @@
android:layout_alignParentStart="true"
android:layout_below="@+id/quotedText"
android:layout_marginTop="@dimen/element_spacing_small"
android:drawableLeft="@drawable/ic_label_gallery"
android:drawableStart="@drawable/ic_label_gallery"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:visibility="gone">
<org.mariotaku.twidere.view.IconActionView
android:layout_width="@dimen/element_size_small"
android:layout_height="@dimen/element_size_small"
android:layout_weight="0"
android:color="?android:textColorSecondary"
android:scaleType="centerInside"
android:src="@drawable/ic_action_gallery"
tools:tint="?android:textColorSecondary"/>
<org.mariotaku.twidere.view.FixedTextView
android:id="@+id/quotedMediaLabelText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/media"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold"/>
</LinearLayout>
android:text="@string/media"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold"
app:iabColor="?android:textColorSecondary"
tools:visibility="gone"/>
<org.mariotaku.twidere.view.CardMediaContainer
android:id="@+id/quotedMediaPreview"

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>ic_label_gallery-mdpi</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Action-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="ic_label_gallery-mdpi">
<g id="image_image" transform="translate(2.000000, 2.000000)">
<g id="Group">
<polygon id="Shape" points="0 0 20 0 20 20 0 20"></polygon>
<path d="M17.5,15.8333333 L17.5,4.16666667 C17.5,3.25 16.75,2.5 15.8333333,2.5 L4.16666667,2.5 C3.25,2.5 2.5,3.25 2.5,4.16666667 L2.5,15.8333333 C2.5,16.75 3.25,17.5 4.16666667,17.5 L15.8333333,17.5 C16.75,17.5 17.5,16.75 17.5,15.8333333 Z M7.08333333,11.25 L9.16666667,13.7583333 L12.0833333,10 L15.8333333,15 L4.16666667,15 L7.08333333,11.25 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>ic_label_video-mdpi</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Action-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="ic_label_video-mdpi">
<g id="Group" transform="translate(2.000000, 2.000000)">
<path d="M15,3.33333333 L16.6666667,6.66666667 L14.1666667,6.66666667 L12.5,3.33333333 L10.8333333,3.33333333 L12.5,6.66666667 L10,6.66666667 L8.33333333,3.33333333 L6.66666667,3.33333333 L8.33333333,6.66666667 L5.83333333,6.66666667 L4.16666667,3.33333333 L3.33333333,3.33333333 C2.41666667,3.33333333 1.675,4.08333333 1.675,5 L1.66666667,15 C1.66666667,15.9166667 2.41666667,16.6666667 3.33333333,16.6666667 L16.6666667,16.6666667 C17.5833333,16.6666667 18.3333333,15.9166667 18.3333333,15 L18.3333333,3.33333333 L15,3.33333333 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
<polygon id="Shape" points="0 0 20 0 20 20 0 20"></polygon>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>ic_label_warning-mdpi</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Action-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="ic_label_warning-mdpi">
<g id="Group" transform="translate(2.000000, 2.000000)">
<polygon id="Shape" points="0 0 20 0 20 20 0 20"></polygon>
<path d="M0.833333333,17.5 L19.1666667,17.5 L10,1.66666667 L0.833333333,17.5 Z M10.8333333,15 L9.16666667,15 L9.16666667,13.3333333 L10.8333333,13.3333333 L10.8333333,15 Z M10.8333333,11.6666667 L9.16666667,11.6666667 L9.16666667,8.33333333 L10.8333333,8.33333333 L10.8333333,11.6666667 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB