fixed #672
This commit is contained in:
parent
2bab27f68c
commit
ad1f14c20c
|
@ -1,188 +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.adapter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.graphics.PorterDuff.Mode;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v4.widget.SimpleCursorAdapter;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.FilterQueryProvider;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.mariotaku.twidere.Constants;
|
|
||||||
import org.mariotaku.twidere.R;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Suggestions;
|
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
|
||||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
|
||||||
import org.mariotaku.twidere.util.UserColorNameManager;
|
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class ComposeAutoCompleteAdapter extends SimpleCursorAdapter implements Constants {
|
|
||||||
|
|
||||||
private static final String[] FROM = new String[0];
|
|
||||||
private static final int[] TO = new int[0];
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
MediaLoaderWrapper mProfileImageLoader;
|
|
||||||
@Inject
|
|
||||||
SharedPreferencesWrapper mPreferences;
|
|
||||||
@Inject
|
|
||||||
UserColorNameManager mUserColorNameManager;
|
|
||||||
|
|
||||||
private final boolean mDisplayProfileImage;
|
|
||||||
|
|
||||||
private int mTypeIdx, mIconIdx, mTitleIdx, mSummaryIdx, mExtraIdIdx, mValueIdx;
|
|
||||||
private UserKey accountKey;
|
|
||||||
private char mToken;
|
|
||||||
|
|
||||||
public ComposeAutoCompleteAdapter(final Context context) {
|
|
||||||
super(context, R.layout.list_item_auto_complete, null, FROM, TO, 0);
|
|
||||||
GeneralComponentHelper.build(context).inject(this);
|
|
||||||
mDisplayProfileImage = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindView(final View view, final Context context, final Cursor cursor) {
|
|
||||||
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
|
|
||||||
final TextView text2 = (TextView) view.findViewById(android.R.id.text2);
|
|
||||||
final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
|
|
||||||
|
|
||||||
// Clear images in order to prevent images in recycled view shown.
|
|
||||||
icon.setImageDrawable(null);
|
|
||||||
|
|
||||||
if (Suggestions.AutoComplete.TYPE_USERS.equals(cursor.getString(mTypeIdx))) {
|
|
||||||
text1.setText(mUserColorNameManager.getUserNickname(cursor.getString(mExtraIdIdx),
|
|
||||||
cursor.getString(mTitleIdx)));
|
|
||||||
text2.setText(String.format("@%s", cursor.getString(mSummaryIdx)));
|
|
||||||
if (mDisplayProfileImage) {
|
|
||||||
final String profileImageUrl = cursor.getString(mIconIdx);
|
|
||||||
mProfileImageLoader.displayProfileImage(icon, profileImageUrl);
|
|
||||||
} else {
|
|
||||||
mProfileImageLoader.cancelDisplayTask(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
icon.clearColorFilter();
|
|
||||||
} else {
|
|
||||||
text1.setText(String.format("#%s", cursor.getString(mTitleIdx)));
|
|
||||||
text2.setText(R.string.hashtag);
|
|
||||||
|
|
||||||
icon.setImageResource(R.drawable.ic_action_hashtag);
|
|
||||||
icon.setColorFilter(text1.getCurrentTextColor(), Mode.SRC_ATOP);
|
|
||||||
}
|
|
||||||
icon.setVisibility(mDisplayProfileImage ? View.VISIBLE : View.GONE);
|
|
||||||
super.bindView(view, context, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeCursor() {
|
|
||||||
final Cursor cursor = swapCursor(null);
|
|
||||||
if (cursor == null) return;
|
|
||||||
if (!cursor.isClosed()) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CharSequence convertToString(final Cursor cursor) {
|
|
||||||
switch (StringUtils.defaultIfEmpty(cursor.getString(mTypeIdx), "")) {
|
|
||||||
case Suggestions.AutoComplete.TYPE_HASHTAGS: {
|
|
||||||
return '#' + cursor.getString(mValueIdx);
|
|
||||||
}
|
|
||||||
case Suggestions.AutoComplete.TYPE_USERS: {
|
|
||||||
return '@' + cursor.getString(mValueIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cursor.getString(mValueIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cursor runQueryOnBackgroundThread(final CharSequence constraint) {
|
|
||||||
if (TextUtils.isEmpty(constraint)) return null;
|
|
||||||
char token = constraint.charAt(0);
|
|
||||||
if (getNormalizedSymbol(token) == getNormalizedSymbol(mToken)) {
|
|
||||||
final FilterQueryProvider filter = getFilterQueryProvider();
|
|
||||||
if (filter != null) return filter.runQuery(constraint);
|
|
||||||
}
|
|
||||||
mToken = token;
|
|
||||||
final Uri.Builder builder = Suggestions.AutoComplete.CONTENT_URI.buildUpon();
|
|
||||||
builder.appendQueryParameter(QUERY_PARAM_QUERY, String.valueOf(constraint.subSequence(1, constraint.length())));
|
|
||||||
switch (getNormalizedSymbol(token)) {
|
|
||||||
case '#': {
|
|
||||||
builder.appendQueryParameter(QUERY_PARAM_TYPE, Suggestions.AutoComplete.TYPE_HASHTAGS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '@': {
|
|
||||||
builder.appendQueryParameter(QUERY_PARAM_TYPE, Suggestions.AutoComplete.TYPE_USERS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, String.valueOf(accountKey));
|
|
||||||
return mContext.getContentResolver().query(builder.build(), Suggestions.AutoComplete.COLUMNS,
|
|
||||||
null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setAccountKey(UserKey accountKey) {
|
|
||||||
this.accountKey = accountKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserKey getAccountKey() {
|
|
||||||
return accountKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Cursor swapCursor(@Nullable final Cursor cursor) {
|
|
||||||
if (cursor != null) {
|
|
||||||
mTypeIdx = cursor.getColumnIndex(Suggestions.AutoComplete.TYPE);
|
|
||||||
mTitleIdx = cursor.getColumnIndex(Suggestions.AutoComplete.TITLE);
|
|
||||||
mSummaryIdx = cursor.getColumnIndex(Suggestions.AutoComplete.SUMMARY);
|
|
||||||
mExtraIdIdx = cursor.getColumnIndex(Suggestions.AutoComplete.EXTRA_ID);
|
|
||||||
mIconIdx = cursor.getColumnIndex(Suggestions.AutoComplete.ICON);
|
|
||||||
mValueIdx = cursor.getColumnIndex(Suggestions.AutoComplete.VALUE);
|
|
||||||
}
|
|
||||||
return super.swapCursor(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static char getNormalizedSymbol(final char character) {
|
|
||||||
switch (character) {
|
|
||||||
case '\uff20':
|
|
||||||
case '@':
|
|
||||||
return '@';
|
|
||||||
case '\uff03':
|
|
||||||
case '#':
|
|
||||||
return '#';
|
|
||||||
}
|
|
||||||
return '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -24,8 +24,6 @@ import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.internal.widget.PreferenceImageView;
|
import android.support.v7.internal.widget.PreferenceImageView;
|
||||||
|
@ -35,19 +33,14 @@ import android.support.v7.preference.PreferenceManager;
|
||||||
import android.support.v7.preference.PreferenceViewHolder;
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
import android.support.v7.widget.SwitchCompat;
|
import android.support.v7.widget.SwitchCompat;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
|
||||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
|
||||||
|
|
||||||
import org.mariotaku.twidere.Constants;
|
import org.mariotaku.twidere.Constants;
|
||||||
import org.mariotaku.twidere.R;
|
import org.mariotaku.twidere.R;
|
||||||
import org.mariotaku.twidere.model.AccountDetails;
|
import org.mariotaku.twidere.model.AccountDetails;
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils;
|
import org.mariotaku.twidere.model.util.AccountUtils;
|
||||||
import org.mariotaku.twidere.util.BitmapUtils;
|
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
||||||
|
|
||||||
|
@ -101,8 +94,7 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
|
||||||
return mSwitchDefault;
|
return mSwitchDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class AccountItemPreference extends Preference implements ImageLoadingListener,
|
public static final class AccountItemPreference extends Preference implements OnSharedPreferenceChangeListener {
|
||||||
OnSharedPreferenceChangeListener {
|
|
||||||
|
|
||||||
private final AccountDetails mAccount;
|
private final AccountDetails mAccount;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -125,33 +117,9 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
|
||||||
mSwitchPreference.registerOnSharedPreferenceChangeListener(this);
|
mSwitchPreference.registerOnSharedPreferenceChangeListener(this);
|
||||||
setTitle(mAccount.user.name);
|
setTitle(mAccount.user.name);
|
||||||
setSummary(String.format("@%s", mAccount.user.screen_name));
|
setSummary(String.format("@%s", mAccount.user.screen_name));
|
||||||
mImageLoader.loadProfileImage(mAccount, this);
|
|
||||||
setWidgetLayoutResource(R.layout.layout_preference_switch_indicator);
|
setWidgetLayoutResource(R.layout.layout_preference_switch_indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadingCancelled(final String imageUri, final View view) {
|
|
||||||
// setIcon(R.drawable.ic_profile_image_default);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) {
|
|
||||||
final Bitmap roundedBitmap = BitmapUtils.getCircleBitmap(loadedImage);
|
|
||||||
final BitmapDrawable icon = new BitmapDrawable(getContext().getResources(), roundedBitmap);
|
|
||||||
icon.setGravity(Gravity.FILL);
|
|
||||||
setIcon(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadingFailed(final String imageUri, final View view, final FailReason failReason) {
|
|
||||||
// setIcon(R.drawable.ic_profile_image_default);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadingStarted(final String imageUri, final View view) {
|
|
||||||
// setIcon(R.drawable.ic_profile_image_default);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
|
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
|
||||||
notifyChanged();
|
notifyChanged();
|
||||||
|
|
|
@ -17,15 +17,7 @@
|
||||||
package org.mariotaku.twidere.util;
|
package org.mariotaku.twidere.util;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.PorterDuffXfermode;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -38,27 +30,6 @@ public class BitmapUtils {
|
||||||
private BitmapUtils() {
|
private BitmapUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static String getImageMimeType(ContentResolver cr, final Uri uri) {
|
public static String getImageMimeType(ContentResolver cr, final Uri uri) {
|
||||||
if (uri == null) return null;
|
if (uri == null) return null;
|
||||||
|
|
|
@ -1,145 +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.view.holder;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.support.v4.text.BidiFormatter;
|
|
||||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.mariotaku.twidere.R;
|
|
||||||
import org.mariotaku.twidere.adapter.iface.IGroupsAdapter;
|
|
||||||
import org.mariotaku.twidere.model.ParcelableGroup;
|
|
||||||
import org.mariotaku.twidere.model.util.UserKeyUtils;
|
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
|
||||||
import org.mariotaku.twidere.util.Utils;
|
|
||||||
import org.mariotaku.twidere.view.NameView;
|
|
||||||
import org.mariotaku.twidere.view.iface.IColorLabelView;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 15/4/29.
|
|
||||||
*/
|
|
||||||
public class GroupViewHolder extends ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|
||||||
|
|
||||||
private final IGroupsAdapter<?> adapter;
|
|
||||||
|
|
||||||
private final IColorLabelView itemContent;
|
|
||||||
private final ImageView profileImageView;
|
|
||||||
private final NameView nameView;
|
|
||||||
private final TextView externalIndicator;
|
|
||||||
private final TextView descriptionView;
|
|
||||||
private final TextView membersCountView;
|
|
||||||
private final TextView adminsCountView;
|
|
||||||
|
|
||||||
private IGroupsAdapter.GroupAdapterListener groupClickListener;
|
|
||||||
|
|
||||||
public GroupViewHolder(IGroupsAdapter<?> adapter, View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
itemContent = (IColorLabelView) itemView.findViewById(R.id.itemContent);
|
|
||||||
this.adapter = adapter;
|
|
||||||
profileImageView = (ImageView) itemView.findViewById(R.id.profileImage);
|
|
||||||
nameView = (NameView) itemView.findViewById(R.id.name);
|
|
||||||
externalIndicator = (TextView) itemView.findViewById(R.id.externalIndicator);
|
|
||||||
descriptionView = (TextView) itemView.findViewById(R.id.description);
|
|
||||||
membersCountView = (TextView) itemView.findViewById(R.id.membersCount);
|
|
||||||
adminsCountView = (TextView) itemView.findViewById(R.id.adminsCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void displayGroup(ParcelableGroup group) {
|
|
||||||
final Context context = itemView.getContext();
|
|
||||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
|
||||||
final BidiFormatter formatter = adapter.getBidiFormatter();
|
|
||||||
|
|
||||||
nameView.setName(group.fullname);
|
|
||||||
nameView.setScreenName("!" + group.nickname);
|
|
||||||
|
|
||||||
nameView.updateText(formatter);
|
|
||||||
final String groupHost = UserKeyUtils.getUserHost(group.url, group.account_key.getHost());
|
|
||||||
if (UserKeyUtils.isSameHost(group.account_key.getHost(), groupHost)) {
|
|
||||||
externalIndicator.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
externalIndicator.setVisibility(View.VISIBLE);
|
|
||||||
externalIndicator.setText(context.getString(R.string.external_group_host_format,
|
|
||||||
groupHost));
|
|
||||||
}
|
|
||||||
if (adapter.getProfileImageEnabled()) {
|
|
||||||
profileImageView.setVisibility(View.VISIBLE);
|
|
||||||
loader.displayProfileImage(profileImageView, group.homepage_logo);
|
|
||||||
} else {
|
|
||||||
profileImageView.setVisibility(View.GONE);
|
|
||||||
loader.cancelDisplayTask(profileImageView);
|
|
||||||
}
|
|
||||||
descriptionView.setVisibility(TextUtils.isEmpty(group.description) ? View.GONE : View.VISIBLE);
|
|
||||||
descriptionView.setText(formatter.unicodeWrap(group.description));
|
|
||||||
membersCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), group.member_count));
|
|
||||||
adminsCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), group.admin_count));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnClickListeners() {
|
|
||||||
setGroupClickListener(adapter.getGroupAdapterListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (groupClickListener == null) return;
|
|
||||||
switch (v.getId()) {
|
|
||||||
case R.id.itemContent: {
|
|
||||||
groupClickListener.onGroupClick(this, getLayoutPosition());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View v) {
|
|
||||||
if (groupClickListener == null) return false;
|
|
||||||
switch (v.getId()) {
|
|
||||||
case R.id.itemContent: {
|
|
||||||
return groupClickListener.onGroupLongClick(this, getLayoutPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGroupClickListener(IGroupsAdapter.GroupAdapterListener listener) {
|
|
||||||
groupClickListener = listener;
|
|
||||||
((View) itemContent).setOnClickListener(this);
|
|
||||||
((View) itemContent).setOnLongClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setupViewOptions() {
|
|
||||||
setTextSize(adapter.getTextSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTextSize(final float textSize) {
|
|
||||||
descriptionView.setTextSize(textSize);
|
|
||||||
externalIndicator.setTextSize(textSize);
|
|
||||||
nameView.setPrimaryTextSize(textSize);
|
|
||||||
nameView.setSecondaryTextSize(textSize * 0.75f);
|
|
||||||
membersCountView.setTextSize(textSize);
|
|
||||||
adminsCountView.setTextSize(textSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,57 +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.view.holder;
|
|
||||||
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import org.mariotaku.twidere.R;
|
|
||||||
import org.mariotaku.twidere.adapter.MessageConversationAdapter;
|
|
||||||
import org.mariotaku.twidere.model.ParcelableDirectMessageCursorIndices;
|
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 15/4/25.
|
|
||||||
*/
|
|
||||||
public class IncomingMessageViewHolder extends MessageViewHolder {
|
|
||||||
|
|
||||||
private final ImageView profileImageView;
|
|
||||||
|
|
||||||
public IncomingMessageViewHolder(MessageConversationAdapter adapter, View itemView) {
|
|
||||||
super(adapter, itemView);
|
|
||||||
profileImageView = (ImageView) itemView.findViewById(R.id.profileImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void displayMessage(Cursor cursor, ParcelableDirectMessageCursorIndices indices) {
|
|
||||||
super.displayMessage(cursor, indices);
|
|
||||||
final MediaLoaderWrapper wrapper = adapter.getMediaLoader();
|
|
||||||
if (adapter.getProfileImageEnabled()) {
|
|
||||||
profileImageView.setVisibility(View.VISIBLE);
|
|
||||||
wrapper.displayProfileImage(profileImageView, cursor.getString(indices.sender_profile_image_url));
|
|
||||||
} else {
|
|
||||||
profileImageView.setVisibility(View.GONE);
|
|
||||||
wrapper.cancelDisplayTask(profileImageView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,127 +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.holder;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.support.annotation.UiThread;
|
|
||||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.mariotaku.twidere.R;
|
|
||||||
import org.mariotaku.twidere.adapter.MessageEntriesAdapter;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
|
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
|
||||||
import org.mariotaku.twidere.util.UserColorNameManager;
|
|
||||||
import org.mariotaku.twidere.view.NameView;
|
|
||||||
import org.mariotaku.twidere.view.ShortTimeView;
|
|
||||||
import org.mariotaku.twidere.view.iface.IColorLabelView;
|
|
||||||
|
|
||||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
|
||||||
|
|
||||||
public class MessageEntryViewHolder extends ViewHolder implements OnClickListener {
|
|
||||||
|
|
||||||
public final ImageView profileImage;
|
|
||||||
public final NameView nameView;
|
|
||||||
public final TextView textView;
|
|
||||||
public final ShortTimeView timeView;
|
|
||||||
private final MessageEntriesAdapter adapter;
|
|
||||||
private final IColorLabelView content;
|
|
||||||
|
|
||||||
public MessageEntryViewHolder(final MessageEntriesAdapter adapter, final View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
this.adapter = adapter;
|
|
||||||
content = (IColorLabelView) itemView.findViewById(R.id.content);
|
|
||||||
profileImage = (ImageView) itemView.findViewById(R.id.profileImage);
|
|
||||||
nameView = (NameView) itemView.findViewById(R.id.name);
|
|
||||||
textView = (TextView) itemView.findViewById(R.id.text);
|
|
||||||
timeView = (ShortTimeView) itemView.findViewById(R.id.time);
|
|
||||||
|
|
||||||
setTextSize(adapter.getTextSize());
|
|
||||||
itemView.setOnClickListener(this);
|
|
||||||
profileImage.setOnClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
public void displayMessage(Cursor cursor, boolean isUnread) {
|
|
||||||
final Context context = adapter.getContext();
|
|
||||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
|
||||||
final UserColorNameManager manager = adapter.getUserColorNameManager();
|
|
||||||
|
|
||||||
final UserKey accountKey = UserKey.valueOf(cursor.getString(ConversationEntries.IDX_ACCOUNT_KEY));
|
|
||||||
final UserKey conversationId = UserKey.valueOf(cursor.getString(ConversationEntries.IDX_CONVERSATION_ID));
|
|
||||||
final long timestamp = cursor.getLong(ConversationEntries.IDX_MESSAGE_TIMESTAMP);
|
|
||||||
final boolean isOutgoing = cursor.getInt(ConversationEntries.IDX_IS_OUTGOING) == 1;
|
|
||||||
|
|
||||||
final String name = cursor.getString(ConversationEntries.IDX_NAME);
|
|
||||||
final String screenName = cursor.getString(ConversationEntries.IDX_SCREEN_NAME);
|
|
||||||
|
|
||||||
nameView.setName(manager.getUserNickname(conversationId, name));
|
|
||||||
nameView.setScreenName("@" + screenName);
|
|
||||||
nameView.updateText(adapter.getBidiFormatter());
|
|
||||||
textView.setText(toPlainText(cursor.getString(ConversationEntries.IDX_TEXT_UNESCAPED)));
|
|
||||||
timeView.setTime(timestamp);
|
|
||||||
if (isOutgoing) {
|
|
||||||
timeView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_indicator_sent, 0);
|
|
||||||
} else {
|
|
||||||
timeView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
nameView.setTypeface(null, isUnread && !isOutgoing ? Typeface.BOLD : Typeface.NORMAL);
|
|
||||||
textView.setTypeface(null, isUnread && !isOutgoing ? Typeface.BOLD : Typeface.NORMAL);
|
|
||||||
if (adapter.shouldShowAccountsColor()) {
|
|
||||||
// FIXME draw account color
|
|
||||||
} else {
|
|
||||||
content.drawEnd();
|
|
||||||
}
|
|
||||||
content.drawStart(manager.getUserColor(conversationId));
|
|
||||||
|
|
||||||
final String profileImage = cursor.getString(ConversationEntries.IDX_PROFILE_IMAGE_URL);
|
|
||||||
loader.displayProfileImage(this.profileImage, profileImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
switch (v.getId()) {
|
|
||||||
case R.id.profileImage: {
|
|
||||||
adapter.onUserProfileClick(getLayoutPosition());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
if (v == itemView) {
|
|
||||||
adapter.onMessageClick(getLayoutPosition());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTextSize(final float textSize) {
|
|
||||||
nameView.setPrimaryTextSize(textSize * 1.1f);
|
|
||||||
nameView.setSecondaryTextSize(textSize);
|
|
||||||
textView.setTextSize(textSize);
|
|
||||||
timeView.setTextSize(textSize * 0.85f);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,140 +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.holder;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.ColorStateList;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
|
||||||
import android.text.SpannableStringBuilder;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.mariotaku.messagebubbleview.library.MessageBubbleView;
|
|
||||||
import org.mariotaku.twidere.R;
|
|
||||||
import org.mariotaku.twidere.adapter.MessageConversationAdapter;
|
|
||||||
import org.mariotaku.twidere.model.ParcelableDirectMessageCursorIndices;
|
|
||||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
|
||||||
import org.mariotaku.twidere.model.SpanItem;
|
|
||||||
import org.mariotaku.twidere.model.UserKey;
|
|
||||||
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
|
|
||||||
import org.mariotaku.twidere.util.JsonSerializer;
|
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
|
||||||
import org.mariotaku.twidere.util.ThemeUtils;
|
|
||||||
import org.mariotaku.twidere.util.TwidereColorUtils;
|
|
||||||
import org.mariotaku.twidere.util.TwidereLinkify;
|
|
||||||
import org.mariotaku.twidere.util.Utils;
|
|
||||||
import org.mariotaku.twidere.view.CardMediaContainer;
|
|
||||||
|
|
||||||
public class MessageViewHolder extends ViewHolder {
|
|
||||||
|
|
||||||
public final CardMediaContainer mediaContainer;
|
|
||||||
public final TextView textView, time;
|
|
||||||
|
|
||||||
private final MessageBubbleView messageContent;
|
|
||||||
protected final MessageConversationAdapter adapter;
|
|
||||||
|
|
||||||
private final int textColorPrimary, textColorPrimaryInverse, textColorSecondary, textColorSecondaryInverse;
|
|
||||||
|
|
||||||
|
|
||||||
public MessageViewHolder(final MessageConversationAdapter adapter, final View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
this.adapter = adapter;
|
|
||||||
final Context context = itemView.getContext();
|
|
||||||
final TypedArray a = context.obtainStyledAttributes(R.styleable.MessageViewHolder);
|
|
||||||
textColorPrimary = a.getColor(R.styleable.MessageViewHolder_android_textColorPrimary, 0);
|
|
||||||
textColorPrimaryInverse = a.getColor(R.styleable.MessageViewHolder_android_textColorPrimaryInverse, 0);
|
|
||||||
textColorSecondary = a.getColor(R.styleable.MessageViewHolder_android_textColorSecondary, 0);
|
|
||||||
textColorSecondaryInverse = a.getColor(R.styleable.MessageViewHolder_android_textColorSecondaryInverse, 0);
|
|
||||||
a.recycle();
|
|
||||||
messageContent = (MessageBubbleView) itemView.findViewById(R.id.messageContent);
|
|
||||||
messageContent.setOnLongClickListener(new View.OnLongClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View v) {
|
|
||||||
itemView.getParent().showContextMenuForChild(itemView);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
messageContent.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
itemView.getParent().showContextMenuForChild(itemView);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
textView = (TextView) itemView.findViewById(R.id.text);
|
|
||||||
time = (TextView) itemView.findViewById(R.id.time);
|
|
||||||
mediaContainer = (CardMediaContainer) itemView.findViewById(R.id.media_preview_container);
|
|
||||||
mediaContainer.setStyle(adapter.getMediaPreviewStyle());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void displayMessage(Cursor cursor, ParcelableDirectMessageCursorIndices indices) {
|
|
||||||
final Context context = adapter.getContext();
|
|
||||||
final TwidereLinkify linkify = adapter.getLinkify();
|
|
||||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
|
||||||
|
|
||||||
final UserKey accountKey = UserKey.valueOf(cursor.getString(indices.account_key));
|
|
||||||
final long timestamp = cursor.getLong(indices.timestamp);
|
|
||||||
final ParcelableMedia[] media = JsonSerializer.parseArray(cursor.getString(indices.media),
|
|
||||||
ParcelableMedia.class);
|
|
||||||
final SpanItem[] spans = JsonSerializer.parseArray(cursor.getString(indices.spans),
|
|
||||||
SpanItem.class);
|
|
||||||
final SpannableStringBuilder text = SpannableStringBuilder.valueOf(cursor.getString(indices.text_unescaped));
|
|
||||||
ParcelableStatusUtils.INSTANCE.applySpans(text, spans);
|
|
||||||
// Detect entity support
|
|
||||||
linkify.applyAllLinks(text, accountKey, false, true);
|
|
||||||
textView.setText(text);
|
|
||||||
time.setText(Utils.formatToLongTimeString(context, timestamp));
|
|
||||||
mediaContainer.setVisibility(media != null && media.length > 0 ? View.VISIBLE : View.GONE);
|
|
||||||
mediaContainer.displayMedia(loader, media, accountKey, adapter.getOnMediaClickListener(), adapter.getMediaLoadingHandler(), getLayoutPosition(), true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMessageColor(int color) {
|
|
||||||
final ColorStateList colorStateList = ColorStateList.valueOf(color);
|
|
||||||
messageContent.setBubbleColor(colorStateList);
|
|
||||||
final int textLuminancePrimary = TwidereColorUtils.getYIQLuminance(textColorPrimary);
|
|
||||||
final int textPrimaryDark, textPrimaryLight, textSecondaryDark, textSecondaryLight;
|
|
||||||
if (textLuminancePrimary < 128) {
|
|
||||||
textPrimaryDark = textColorPrimary;
|
|
||||||
textPrimaryLight = textColorPrimaryInverse;
|
|
||||||
textSecondaryDark = textColorSecondary;
|
|
||||||
textSecondaryLight = textColorSecondaryInverse;
|
|
||||||
} else {
|
|
||||||
textPrimaryDark = textColorPrimaryInverse;
|
|
||||||
textPrimaryLight = textColorPrimary;
|
|
||||||
textSecondaryDark = textColorSecondaryInverse;
|
|
||||||
textSecondaryLight = textColorSecondary;
|
|
||||||
}
|
|
||||||
final int textContrastPrimary = TwidereColorUtils.getContrastYIQ(color,
|
|
||||||
ThemeUtils.ACCENT_COLOR_THRESHOLD, textPrimaryDark, textPrimaryLight);
|
|
||||||
final int textContrastSecondary = TwidereColorUtils.getContrastYIQ(color,
|
|
||||||
ThemeUtils.ACCENT_COLOR_THRESHOLD, textSecondaryDark, textSecondaryLight);
|
|
||||||
textView.setTextColor(textContrastPrimary);
|
|
||||||
textView.setLinkTextColor(textContrastSecondary);
|
|
||||||
time.setTextColor(textContrastSecondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTextSize(final float textSize) {
|
|
||||||
textView.setTextSize(textSize);
|
|
||||||
time.setTextSize(textSize * 0.75f);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,134 +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.view.holder;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.mariotaku.twidere.R;
|
|
||||||
import org.mariotaku.twidere.adapter.iface.IUserListsAdapter;
|
|
||||||
import org.mariotaku.twidere.model.ParcelableUserList;
|
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
|
||||||
import org.mariotaku.twidere.util.UserColorNameManager;
|
|
||||||
import org.mariotaku.twidere.util.Utils;
|
|
||||||
import org.mariotaku.twidere.view.iface.IColorLabelView;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 15/4/29.
|
|
||||||
*/
|
|
||||||
public class UserListViewHolder extends ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|
||||||
|
|
||||||
private final IUserListsAdapter<?> adapter;
|
|
||||||
|
|
||||||
private final IColorLabelView itemContent;
|
|
||||||
private final ImageView profileImageView;
|
|
||||||
private final TextView nameView;
|
|
||||||
private final TextView createdByView;
|
|
||||||
private final TextView descriptionView;
|
|
||||||
private final TextView membersCountView;
|
|
||||||
private final TextView subscribersCountView;
|
|
||||||
|
|
||||||
private IUserListsAdapter.UserListClickListener userListClickListener;
|
|
||||||
|
|
||||||
public UserListViewHolder(IUserListsAdapter<?> adapter, View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
itemContent = (IColorLabelView) itemView.findViewById(R.id.itemContent);
|
|
||||||
this.adapter = adapter;
|
|
||||||
profileImageView = (ImageView) itemView.findViewById(R.id.profileImage);
|
|
||||||
nameView = (TextView) itemView.findViewById(R.id.name);
|
|
||||||
createdByView = (TextView) itemView.findViewById(R.id.createdBy);
|
|
||||||
descriptionView = (TextView) itemView.findViewById(R.id.description);
|
|
||||||
membersCountView = (TextView) itemView.findViewById(R.id.membersCount);
|
|
||||||
subscribersCountView = (TextView) itemView.findViewById(R.id.subscribersCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void displayUserList(ParcelableUserList userList) {
|
|
||||||
|
|
||||||
final Context context = itemView.getContext();
|
|
||||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
|
||||||
final UserColorNameManager manager = adapter.getUserColorNameManager();
|
|
||||||
|
|
||||||
itemContent.drawStart(manager.getUserColor(userList.user_key));
|
|
||||||
nameView.setText(userList.name);
|
|
||||||
final boolean nameFirst = adapter.getNameFirst();
|
|
||||||
final String createdByDisplayName = manager.getDisplayName(userList, nameFirst);
|
|
||||||
createdByView.setText(context.getString(R.string.created_by, createdByDisplayName));
|
|
||||||
|
|
||||||
if (adapter.getProfileImageEnabled()) {
|
|
||||||
profileImageView.setVisibility(View.VISIBLE);
|
|
||||||
loader.displayProfileImage(profileImageView, userList.user_profile_image_url);
|
|
||||||
} else {
|
|
||||||
profileImageView.setVisibility(View.GONE);
|
|
||||||
loader.cancelDisplayTask(profileImageView);
|
|
||||||
}
|
|
||||||
descriptionView.setVisibility(TextUtils.isEmpty(userList.description) ? View.GONE : View.VISIBLE);
|
|
||||||
descriptionView.setText(userList.description);
|
|
||||||
membersCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), userList.members_count));
|
|
||||||
subscribersCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), userList.subscribers_count));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnClickListeners() {
|
|
||||||
setUserListClickListener(adapter.getUserListClickListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (userListClickListener == null) return;
|
|
||||||
switch (v.getId()) {
|
|
||||||
case R.id.itemContent: {
|
|
||||||
userListClickListener.onUserListClick(this, getLayoutPosition());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View v) {
|
|
||||||
if (userListClickListener == null) return false;
|
|
||||||
switch (v.getId()) {
|
|
||||||
case R.id.itemContent: {
|
|
||||||
return userListClickListener.onUserListLongClick(this, getLayoutPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserListClickListener(IUserListsAdapter.UserListClickListener listener) {
|
|
||||||
userListClickListener = listener;
|
|
||||||
((View) itemContent).setOnClickListener(this);
|
|
||||||
((View) itemContent).setOnLongClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setupViewOptions() {
|
|
||||||
setTextSize(adapter.getTextSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTextSize(final float textSize) {
|
|
||||||
nameView.setTextSize(textSize);
|
|
||||||
createdByView.setTextSize(textSize * 0.75f);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -624,6 +624,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
if (mediaMenuItem != null && mediaMenuItem.hasSubMenu()) {
|
if (mediaMenuItem != null && mediaMenuItem.hasSubMenu()) {
|
||||||
MenuUtils.addIntentToMenu(this, mediaMenuItem.subMenu, imageExtensionsIntent, MENU_GROUP_IMAGE_EXTENSION)
|
MenuUtils.addIntentToMenu(this, mediaMenuItem.subMenu, imageExtensionsIntent, MENU_GROUP_IMAGE_EXTENSION)
|
||||||
}
|
}
|
||||||
|
updateViewStyle()
|
||||||
setMenu()
|
setMenu()
|
||||||
updateLocationState()
|
updateLocationState()
|
||||||
notifyAccountSelectionChanged()
|
notifyAccountSelectionChanged()
|
||||||
|
@ -633,6 +634,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||||
updateAttachedMediaView()
|
updateAttachedMediaView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateViewStyle() {
|
||||||
|
accountProfileImage.style = preferences[profileImageStyleKey]
|
||||||
|
}
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||||
val keyCode = event.keyCode
|
val keyCode = event.keyCode
|
||||||
if (KeyEvent.isModifierKey(keyCode)) {
|
if (KeyEvent.isModifierKey(keyCode)) {
|
||||||
|
|
|
@ -19,35 +19,22 @@
|
||||||
|
|
||||||
package org.mariotaku.twidere.adapter
|
package org.mariotaku.twidere.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import kotlinx.android.synthetic.main.list_item_simple_user.view.*
|
import kotlinx.android.synthetic.main.list_item_simple_user.view.*
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.TwidereConstants
|
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper
|
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class AccountsSpinnerAdapter(
|
class AccountsSpinnerAdapter(
|
||||||
context: Context,
|
context: Context,
|
||||||
itemViewResource: Int = R.layout.list_item_simple_user
|
itemViewResource: Int = R.layout.list_item_simple_user
|
||||||
) : ArrayAdapter<AccountDetails>(context, itemViewResource) {
|
) : BaseArrayAdapter<AccountDetails>(context, itemViewResource) {
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var mediaLoader: MediaLoaderWrapper
|
|
||||||
private val displayProfileImage: Boolean
|
|
||||||
private var dummyItemText: String? = null
|
private var dummyItemText: String? = null
|
||||||
|
|
||||||
init {
|
|
||||||
GeneralComponentHelper.build(context).inject(this)
|
|
||||||
displayProfileImage = context.getSharedPreferences(TwidereConstants.SHARED_PREFERENCES_NAME,
|
|
||||||
Context.MODE_PRIVATE).getBoolean(SharedPreferenceConstants.KEY_DISPLAY_PROFILE_IMAGE, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(context: Context, accounts: Collection<AccountDetails>) : this(context) {
|
constructor(context: Context, accounts: Collection<AccountDetails>) : this(context) {
|
||||||
addAll(accounts)
|
addAll(accounts)
|
||||||
}
|
}
|
||||||
|
@ -73,34 +60,26 @@ class AccountsSpinnerAdapter(
|
||||||
val text2 = view.screenName
|
val text2 = view.screenName
|
||||||
val icon = view.profileImage
|
val icon = view.profileImage
|
||||||
if (!item.dummy) {
|
if (!item.dummy) {
|
||||||
if (text1 != null) {
|
text1?.visibility = View.VISIBLE
|
||||||
text1.visibility = View.VISIBLE
|
text1?.text = item.user.name
|
||||||
text1.text = item.user.name
|
text2?.visibility = View.VISIBLE
|
||||||
}
|
@SuppressLint("SetTextI18n")
|
||||||
if (text2 != null) {
|
text2?.text = "@${item.user.screen_name}"
|
||||||
text2.visibility = View.VISIBLE
|
|
||||||
text2.text = String.format("@%s", item.user.screen_name)
|
|
||||||
}
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
icon.visibility = View.VISIBLE
|
if (profileImageEnabled) {
|
||||||
if (displayProfileImage) {
|
icon.visibility = View.VISIBLE
|
||||||
|
icon.style = profileImageStyle
|
||||||
mediaLoader.displayProfileImage(icon, item.user)
|
mediaLoader.displayProfileImage(icon, item.user)
|
||||||
} else {
|
} else {
|
||||||
|
icon.visibility = View.GONE
|
||||||
mediaLoader.cancelDisplayTask(icon)
|
mediaLoader.cancelDisplayTask(icon)
|
||||||
// icon.setImageResource(R.drawable.ic_profile_image_default);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (text1 != null) {
|
text1?.visibility = View.VISIBLE
|
||||||
text1.visibility = View.VISIBLE
|
text1?.text = dummyItemText
|
||||||
text1.text = dummyItemText
|
text2?.visibility = View.GONE
|
||||||
}
|
icon?.visibility = View.GONE
|
||||||
if (text2 != null) {
|
|
||||||
text2.visibility = View.GONE
|
|
||||||
}
|
|
||||||
if (icon != null) {
|
|
||||||
icon.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,10 @@ open class BaseArrayAdapter<T>(
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var preferences: SharedPreferencesWrapper
|
lateinit var preferences: SharedPreferencesWrapper
|
||||||
|
|
||||||
override val profileImageStyle: Int
|
final override val profileImageStyle: Int
|
||||||
override val textSize: Float
|
final override val textSize: Float
|
||||||
override val profileImageEnabled: Boolean
|
final override val profileImageEnabled: Boolean
|
||||||
override val isShowAbsoluteTime: Boolean
|
final override val isShowAbsoluteTime: Boolean
|
||||||
val nameFirst: Boolean
|
val nameFirst: Boolean
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* 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.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.graphics.PorterDuff.Mode
|
||||||
|
import android.support.v4.widget.SimpleCursorAdapter
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import org.apache.commons.lang3.StringUtils
|
||||||
|
import org.mariotaku.kpreferences.get
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
|
import org.mariotaku.twidere.TwidereConstants.*
|
||||||
|
import org.mariotaku.twidere.constant.displayProfileImageKey
|
||||||
|
import org.mariotaku.twidere.constant.profileImageStyleKey
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.Suggestions
|
||||||
|
import org.mariotaku.twidere.util.MediaLoaderWrapper
|
||||||
|
import org.mariotaku.twidere.util.SharedPreferencesWrapper
|
||||||
|
import org.mariotaku.twidere.util.UserColorNameManager
|
||||||
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class ComposeAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context,
|
||||||
|
R.layout.list_item_auto_complete, null, emptyArray(), intArrayOf(), 0) {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var mediaLoader: MediaLoaderWrapper
|
||||||
|
@Inject
|
||||||
|
lateinit var preferences: SharedPreferencesWrapper
|
||||||
|
@Inject
|
||||||
|
lateinit var userColorNameManager: UserColorNameManager
|
||||||
|
|
||||||
|
private val displayProfileImage: Boolean
|
||||||
|
private val profileImageStyle: Int
|
||||||
|
|
||||||
|
private var mTypeIdx: Int = 0
|
||||||
|
private var mIconIdx: Int = 0
|
||||||
|
private var mTitleIdx: Int = 0
|
||||||
|
private var mSummaryIdx: Int = 0
|
||||||
|
private var mExtraIdIdx: Int = 0
|
||||||
|
private var mValueIdx: Int = 0
|
||||||
|
var accountKey: UserKey? = null
|
||||||
|
private var mToken: Char = ' '
|
||||||
|
|
||||||
|
init {
|
||||||
|
GeneralComponentHelper.build(context).inject(this)
|
||||||
|
displayProfileImage = preferences[displayProfileImageKey]
|
||||||
|
profileImageStyle = preferences[profileImageStyleKey]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindView(view: View, context: Context?, cursor: Cursor) {
|
||||||
|
val text1 = view.findViewById(android.R.id.text1) as TextView
|
||||||
|
val text2 = view.findViewById(android.R.id.text2) as TextView
|
||||||
|
val icon = view.findViewById(android.R.id.icon) as ProfileImageView
|
||||||
|
|
||||||
|
icon.style = profileImageStyle
|
||||||
|
|
||||||
|
if (Suggestions.AutoComplete.TYPE_USERS == cursor.getString(mTypeIdx)) {
|
||||||
|
text1.text = userColorNameManager.getUserNickname(cursor.getString(mExtraIdIdx),
|
||||||
|
cursor.getString(mTitleIdx))
|
||||||
|
text2.text = String.format("@%s", cursor.getString(mSummaryIdx))
|
||||||
|
if (displayProfileImage) {
|
||||||
|
val profileImageUrl = cursor.getString(mIconIdx)
|
||||||
|
mediaLoader.displayProfileImage(icon, profileImageUrl)
|
||||||
|
} else {
|
||||||
|
mediaLoader.cancelDisplayTask(icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
icon.clearColorFilter()
|
||||||
|
} else {
|
||||||
|
text1.text = String.format("#%s", cursor.getString(mTitleIdx))
|
||||||
|
text2.setText(R.string.hashtag)
|
||||||
|
|
||||||
|
icon.setImageResource(R.drawable.ic_action_hashtag)
|
||||||
|
icon.setColorFilter(text1.currentTextColor, Mode.SRC_ATOP)
|
||||||
|
}
|
||||||
|
icon.visibility = if (displayProfileImage) View.VISIBLE else View.GONE
|
||||||
|
super.bindView(view, context, cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeCursor() {
|
||||||
|
val cursor = swapCursor(null) ?: return
|
||||||
|
if (!cursor.isClosed) {
|
||||||
|
cursor.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun convertToString(cursor: Cursor?): CharSequence {
|
||||||
|
when (StringUtils.defaultIfEmpty(cursor!!.getString(mTypeIdx), "")) {
|
||||||
|
Suggestions.AutoComplete.TYPE_HASHTAGS -> {
|
||||||
|
return '#' + cursor.getString(mValueIdx)
|
||||||
|
}
|
||||||
|
Suggestions.AutoComplete.TYPE_USERS -> {
|
||||||
|
return '@' + cursor.getString(mValueIdx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cursor.getString(mValueIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
|
||||||
|
if (TextUtils.isEmpty(constraint)) return null
|
||||||
|
val token = constraint[0]
|
||||||
|
if (getNormalizedSymbol(token) == getNormalizedSymbol(mToken)) {
|
||||||
|
val filter = filterQueryProvider
|
||||||
|
if (filter != null) return filter.runQuery(constraint)
|
||||||
|
}
|
||||||
|
mToken = token
|
||||||
|
val builder = Suggestions.AutoComplete.CONTENT_URI.buildUpon()
|
||||||
|
builder.appendQueryParameter(QUERY_PARAM_QUERY, constraint.subSequence(1, constraint.length).toString())
|
||||||
|
when (getNormalizedSymbol(token)) {
|
||||||
|
'#' -> {
|
||||||
|
builder.appendQueryParameter(QUERY_PARAM_TYPE, Suggestions.AutoComplete.TYPE_HASHTAGS)
|
||||||
|
}
|
||||||
|
'@' -> {
|
||||||
|
builder.appendQueryParameter(QUERY_PARAM_TYPE, Suggestions.AutoComplete.TYPE_USERS)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, accountKey.toString())
|
||||||
|
return mContext.contentResolver.query(builder.build(), Suggestions.AutoComplete.COLUMNS,
|
||||||
|
null, null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun swapCursor(cursor: Cursor?): Cursor? {
|
||||||
|
if (cursor != null) {
|
||||||
|
mTypeIdx = cursor.getColumnIndex(Suggestions.AutoComplete.TYPE)
|
||||||
|
mTitleIdx = cursor.getColumnIndex(Suggestions.AutoComplete.TITLE)
|
||||||
|
mSummaryIdx = cursor.getColumnIndex(Suggestions.AutoComplete.SUMMARY)
|
||||||
|
mExtraIdIdx = cursor.getColumnIndex(Suggestions.AutoComplete.EXTRA_ID)
|
||||||
|
mIconIdx = cursor.getColumnIndex(Suggestions.AutoComplete.ICON)
|
||||||
|
mValueIdx = cursor.getColumnIndex(Suggestions.AutoComplete.VALUE)
|
||||||
|
}
|
||||||
|
return super.swapCursor(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private fun getNormalizedSymbol(character: Char): Char {
|
||||||
|
when (character) {
|
||||||
|
'\uff20', '@' -> return '@'
|
||||||
|
'\uff03', '#' -> return '#'
|
||||||
|
}
|
||||||
|
return '\u0000'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -200,10 +200,9 @@ class ParcelableActivitiesAdapter(
|
||||||
}
|
}
|
||||||
ITEM_VIEW_TYPE_TITLE_SUMMARY -> {
|
ITEM_VIEW_TYPE_TITLE_SUMMARY -> {
|
||||||
val view = inflater.inflate(R.layout.card_item_activity_summary_compact, parent, false)
|
val view = inflater.inflate(R.layout.card_item_activity_summary_compact, parent, false)
|
||||||
val holder = ActivityTitleSummaryViewHolder(this,
|
val holder = ActivityTitleSummaryViewHolder(view, this)
|
||||||
view)
|
|
||||||
holder.setOnClickListeners()
|
holder.setOnClickListeners()
|
||||||
holder.setTextSize(textSize)
|
holder.setupViewOptions()
|
||||||
return holder
|
return holder
|
||||||
}
|
}
|
||||||
ITEM_VIEW_TYPE_GAP -> {
|
ITEM_VIEW_TYPE_GAP -> {
|
||||||
|
|
|
@ -63,7 +63,7 @@ class ParcelableGroupsAdapter(context: Context) : LoadMoreSupportAdapter<Recycle
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindGroup(holder: GroupViewHolder, position: Int) {
|
private fun bindGroup(holder: GroupViewHolder, position: Int) {
|
||||||
holder.displayGroup(getGroup(position))
|
holder.displayGroup(getGroup(position)!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
|
|
|
@ -22,7 +22,6 @@ package org.mariotaku.twidere.adapter
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import org.mariotaku.kpreferences.get
|
import org.mariotaku.kpreferences.get
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
|
@ -37,19 +36,14 @@ import org.mariotaku.twidere.view.holder.UserListViewHolder
|
||||||
class ParcelableUserListsAdapter(
|
class ParcelableUserListsAdapter(
|
||||||
context: Context
|
context: Context
|
||||||
) : LoadMoreSupportAdapter<RecyclerView.ViewHolder>(context), IUserListsAdapter<List<ParcelableUserList>> {
|
) : LoadMoreSupportAdapter<RecyclerView.ViewHolder>(context), IUserListsAdapter<List<ParcelableUserList>> {
|
||||||
override val showAccountsColor: Boolean
|
override val showAccountsColor: Boolean = false
|
||||||
get() = false
|
override val nameFirst: Boolean = preferences[nameFirstKey]
|
||||||
override val nameFirst: Boolean
|
|
||||||
override var userListClickListener: IUserListsAdapter.UserListClickListener? = null
|
override var userListClickListener: IUserListsAdapter.UserListClickListener? = null
|
||||||
|
|
||||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||||
private var data: List<ParcelableUserList>? = null
|
private var data: List<ParcelableUserList>? = null
|
||||||
|
|
||||||
|
|
||||||
init {
|
|
||||||
nameFirst = preferences[nameFirstKey]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getData(): List<ParcelableUserList>? {
|
fun getData(): List<ParcelableUserList>? {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
@ -62,7 +56,7 @@ class ParcelableUserListsAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUserList(holder: UserListViewHolder, position: Int) {
|
private fun bindUserList(holder: UserListViewHolder, position: Int) {
|
||||||
holder.displayUserList(getUserList(position))
|
holder.displayUserList(getUserList(position)!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
|
@ -131,9 +125,8 @@ class ParcelableUserListsAdapter(
|
||||||
fun createUserListViewHolder(adapter: IUserListsAdapter<*>,
|
fun createUserListViewHolder(adapter: IUserListsAdapter<*>,
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
parent: ViewGroup): UserListViewHolder {
|
parent: ViewGroup): UserListViewHolder {
|
||||||
val view: View
|
val view = inflater.inflate(R.layout.list_item_user_list, parent, false)
|
||||||
view = inflater.inflate(R.layout.list_item_user_list, parent, false)
|
val holder = UserListViewHolder(view, adapter)
|
||||||
val holder = UserListViewHolder(adapter, view)
|
|
||||||
holder.setOnClickListeners()
|
holder.setOnClickListeners()
|
||||||
holder.setupViewOptions()
|
holder.setupViewOptions()
|
||||||
return holder
|
return holder
|
||||||
|
|
|
@ -19,19 +19,22 @@
|
||||||
|
|
||||||
package org.mariotaku.twidere.adapter
|
package org.mariotaku.twidere.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.support.v4.widget.SimpleCursorAdapter
|
import android.support.v4.widget.SimpleCursorAdapter
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import org.mariotaku.kpreferences.get
|
||||||
import org.mariotaku.sqliteqb.library.Columns
|
import org.mariotaku.sqliteqb.library.Columns
|
||||||
import org.mariotaku.sqliteqb.library.Expression
|
import org.mariotaku.sqliteqb.library.Expression
|
||||||
import org.mariotaku.sqliteqb.library.OrderBy
|
import org.mariotaku.sqliteqb.library.OrderBy
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_DISPLAY_PROFILE_IMAGE
|
import org.mariotaku.twidere.constant.displayProfileImageKey
|
||||||
|
import org.mariotaku.twidere.constant.profileImageStyleKey
|
||||||
|
import org.mariotaku.twidere.model.ParcelableUserCursorIndices
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
|
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
|
||||||
import org.mariotaku.twidere.util.MediaLoaderWrapper
|
import org.mariotaku.twidere.util.MediaLoaderWrapper
|
||||||
|
@ -39,49 +42,53 @@ import org.mariotaku.twidere.util.SharedPreferencesWrapper
|
||||||
import org.mariotaku.twidere.util.UserColorNameManager
|
import org.mariotaku.twidere.util.UserColorNameManager
|
||||||
import org.mariotaku.twidere.util.Utils
|
import org.mariotaku.twidere.util.Utils
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
class UserAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context, R.layout.list_item_auto_complete, null, UserAutoCompleteAdapter.FROM, UserAutoCompleteAdapter.TO, 0) {
|
class UserAutoCompleteAdapter(val context: Context) : SimpleCursorAdapter(context,
|
||||||
|
R.layout.list_item_auto_complete, null, emptyArray(),
|
||||||
|
intArrayOf(), 0) {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var profileImageLoader: MediaLoaderWrapper
|
lateinit var profileImageLoader: MediaLoaderWrapper
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var mPreferences: SharedPreferencesWrapper
|
lateinit var preferences: SharedPreferencesWrapper
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var mUserColorNameManager: UserColorNameManager
|
lateinit var userColorNameManager: UserColorNameManager
|
||||||
|
|
||||||
private val mDisplayProfileImage: Boolean
|
private val displayProfileImage: Boolean
|
||||||
|
private var profileImageStyle: Int
|
||||||
|
|
||||||
private var mIdIdx: Int = 0
|
private var indices: ParcelableUserCursorIndices? = null
|
||||||
private var mNameIdx: Int = 0
|
|
||||||
private var mScreenNameIdx: Int = 0
|
private var accountKey: UserKey? = null
|
||||||
private var mProfileImageIdx: Int = 0
|
|
||||||
private var mAccountKey: UserKey? = null
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
GeneralComponentHelper.build(context).inject(this)
|
GeneralComponentHelper.build(context).inject(this)
|
||||||
mDisplayProfileImage = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true)
|
displayProfileImage = preferences[displayProfileImageKey]
|
||||||
|
profileImageStyle = preferences[profileImageStyleKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindView(view: View, context: Context?, cursor: Cursor) {
|
override fun bindView(view: View, context: Context?, cursor: Cursor) {
|
||||||
|
val indices = this.indices!!
|
||||||
val text1 = view.findViewById(android.R.id.text1) as TextView
|
val text1 = view.findViewById(android.R.id.text1) as TextView
|
||||||
val text2 = view.findViewById(android.R.id.text2) as TextView
|
val text2 = view.findViewById(android.R.id.text2) as TextView
|
||||||
val icon = view.findViewById(android.R.id.icon) as ImageView
|
val icon = view.findViewById(android.R.id.icon) as ProfileImageView
|
||||||
|
|
||||||
// Clear images in order to prevent images in recycled view shown.
|
icon.style = profileImageStyle
|
||||||
icon.setImageDrawable(null)
|
|
||||||
|
|
||||||
text1.text = mUserColorNameManager.getUserNickname(cursor.getString(mIdIdx), cursor.getString(mNameIdx))
|
text1.text = userColorNameManager.getUserNickname(cursor.getString(indices.key), cursor.getString(indices.name))
|
||||||
text2.text = String.format("@%s", cursor.getString(mScreenNameIdx))
|
@SuppressLint("SetTextI18n")
|
||||||
if (mDisplayProfileImage) {
|
text2.text = "@${cursor.getString(indices.screen_name)}"
|
||||||
val profileImageUrl = cursor.getString(mProfileImageIdx)
|
if (displayProfileImage) {
|
||||||
|
val profileImageUrl = cursor.getString(indices.profile_image_url)
|
||||||
profileImageLoader.displayProfileImage(icon, profileImageUrl)
|
profileImageLoader.displayProfileImage(icon, profileImageUrl)
|
||||||
} else {
|
} else {
|
||||||
profileImageLoader.cancelDisplayTask(icon)
|
profileImageLoader.cancelDisplayTask(icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
icon.visibility = if (mDisplayProfileImage) View.VISIBLE else View.GONE
|
icon.visibility = if (displayProfileImage) View.VISIBLE else View.GONE
|
||||||
super.bindView(view, context, cursor)
|
super.bindView(view, context, cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +100,7 @@ class UserAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context, R
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun convertToString(cursor: Cursor?): CharSequence {
|
override fun convertToString(cursor: Cursor?): CharSequence {
|
||||||
return cursor!!.getString(mScreenNameIdx)
|
return cursor!!.getString(indices!!.screen_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
|
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
|
||||||
|
@ -102,7 +109,7 @@ class UserAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context, R
|
||||||
if (filter != null) return filter.runQuery(constraint)
|
if (filter != null) return filter.runQuery(constraint)
|
||||||
val query = constraint.toString()
|
val query = constraint.toString()
|
||||||
val queryEscaped = query.replace("_", "^_")
|
val queryEscaped = query.replace("_", "^_")
|
||||||
val nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager)
|
val nicknameKeys = Utils.getMatchedNicknameKeys(query, userColorNameManager)
|
||||||
val usersSelection = Expression.or(
|
val usersSelection = Expression.or(
|
||||||
Expression.likeRaw(Columns.Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
|
Expression.likeRaw(Columns.Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
|
||||||
Expression.likeRaw(Columns.Column(CachedUsers.NAME), "?||'%'", "^"),
|
Expression.likeRaw(Columns.Column(CachedUsers.NAME), "?||'%'", "^"),
|
||||||
|
@ -111,31 +118,23 @@ class UserAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context, R
|
||||||
val order = arrayOf(CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME, CachedUsers.NAME)
|
val order = arrayOf(CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME, CachedUsers.NAME)
|
||||||
val ascending = booleanArrayOf(false, false, true, true)
|
val ascending = booleanArrayOf(false, false, true, true)
|
||||||
val orderBy = OrderBy(order, ascending)
|
val orderBy = OrderBy(order, ascending)
|
||||||
val uri = Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, mAccountKey.toString())
|
val uri = Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, accountKey.toString())
|
||||||
return mContext.contentResolver.query(uri, CachedUsers.COLUMNS, usersSelection.sql,
|
@SuppressLint("Recycle")
|
||||||
|
val cursor = context.contentResolver.query(uri, CachedUsers.COLUMNS, usersSelection.sql,
|
||||||
selectionArgs, orderBy.sql)
|
selectionArgs, orderBy.sql)
|
||||||
|
return cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun setAccountKey(accountKey: UserKey) {
|
fun setAccountKey(accountKey: UserKey) {
|
||||||
mAccountKey = accountKey
|
this.accountKey = accountKey
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun swapCursor(cursor: Cursor?): Cursor? {
|
override fun swapCursor(cursor: Cursor?): Cursor? {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
mIdIdx = cursor.getColumnIndex(CachedUsers.USER_KEY)
|
indices = ParcelableUserCursorIndices(cursor)
|
||||||
mNameIdx = cursor.getColumnIndex(CachedUsers.NAME)
|
|
||||||
mScreenNameIdx = cursor.getColumnIndex(CachedUsers.SCREEN_NAME)
|
|
||||||
mProfileImageIdx = cursor.getColumnIndex(CachedUsers.PROFILE_IMAGE_URL)
|
|
||||||
}
|
}
|
||||||
return super.swapCursor(cursor)
|
return super.swapCursor(cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private val FROM = arrayOfNulls<String>(0)
|
|
||||||
private val TO = IntArray(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import android.view.View.OnClickListener
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import kotlinx.android.synthetic.main.header_drawer_account_selector.view.*
|
import kotlinx.android.synthetic.main.header_drawer_account_selector.view.*
|
||||||
|
import org.mariotaku.kpreferences.get
|
||||||
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
|
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
|
||||||
import org.mariotaku.ktextension.convert
|
import org.mariotaku.ktextension.convert
|
||||||
import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe
|
import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe
|
||||||
|
@ -65,6 +66,7 @@ import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.annotation.CustomTabType
|
import org.mariotaku.twidere.annotation.CustomTabType
|
||||||
import org.mariotaku.twidere.annotation.Referral
|
import org.mariotaku.twidere.annotation.Referral
|
||||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
||||||
|
import org.mariotaku.twidere.constant.profileImageStyleKey
|
||||||
import org.mariotaku.twidere.extension.model.setActivated
|
import org.mariotaku.twidere.extension.model.setActivated
|
||||||
import org.mariotaku.twidere.fragment.AccountsDashboardFragment.AccountsInfo
|
import org.mariotaku.twidere.fragment.AccountsDashboardFragment.AccountsInfo
|
||||||
import org.mariotaku.twidere.menu.AccountToggleProvider
|
import org.mariotaku.twidere.menu.AccountToggleProvider
|
||||||
|
@ -159,7 +161,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
})
|
})
|
||||||
|
|
||||||
profileContainer.setOnClickListener(this)
|
profileContainer.setOnClickListener(this)
|
||||||
|
accountProfileImageView.style = preferences[profileImageStyleKey]
|
||||||
accountProfileBanner.setInAnimation(context, android.R.anim.fade_in)
|
accountProfileBanner.setInAnimation(context, android.R.anim.fade_in)
|
||||||
accountProfileBanner.setOutAnimation(context, android.R.anim.fade_out)
|
accountProfileBanner.setOutAnimation(context, android.R.anim.fade_out)
|
||||||
accountProfileBanner.setFactory {
|
accountProfileBanner.setFactory {
|
||||||
|
@ -574,13 +576,17 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
|
|
||||||
internal class AccountSpaceViewHolder(itemView: View) : RecyclerPagerAdapter.ViewHolder(itemView)
|
internal class AccountSpaceViewHolder(itemView: View) : RecyclerPagerAdapter.ViewHolder(itemView)
|
||||||
|
|
||||||
internal class AccountProfileImageViewHolder(val adapter: AccountSelectorAdapter, itemView: View) : RecyclerPagerAdapter.ViewHolder(itemView), OnClickListener {
|
internal class AccountProfileImageViewHolder(
|
||||||
|
val adapter: AccountSelectorAdapter,
|
||||||
|
itemView: View
|
||||||
|
) : RecyclerPagerAdapter.ViewHolder(itemView), OnClickListener {
|
||||||
|
|
||||||
val iconView: ShapedImageView
|
val iconView: ShapedImageView
|
||||||
|
|
||||||
init {
|
init {
|
||||||
itemView.setOnClickListener(this)
|
itemView.setOnClickListener(this)
|
||||||
iconView = itemView.findViewById(android.R.id.icon) as ShapedImageView
|
iconView = itemView.findViewById(android.R.id.icon) as ShapedImageView
|
||||||
|
iconView.style = adapter.profileImageStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
|
@ -593,7 +599,9 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
private val inflater: LayoutInflater,
|
private val inflater: LayoutInflater,
|
||||||
private val fragment: AccountsDashboardFragment
|
private val fragment: AccountsDashboardFragment
|
||||||
) : RecyclerPagerAdapter() {
|
) : RecyclerPagerAdapter() {
|
||||||
private val mediaLoader: MediaLoaderWrapper
|
|
||||||
|
internal var profileImageStyle: Int = fragment.preferences[profileImageStyleKey]
|
||||||
|
internal var mediaLoader: MediaLoaderWrapper = fragment.mediaLoader
|
||||||
|
|
||||||
var accounts: Array<AccountDetails>? = null
|
var accounts: Array<AccountDetails>? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -619,9 +627,6 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||||
notifyPagesChanged(invalidateCache = true)
|
notifyPagesChanged(invalidateCache = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
mediaLoader = fragment.mediaLoader
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAdapterAccount(position: Int): AccountDetails? {
|
fun getAdapterAccount(position: Int): AccountDetails? {
|
||||||
return accounts?.getOrNull(position - accountStart + 1)
|
return accounts?.getOrNull(position - accountStart + 1)
|
||||||
|
|
|
@ -301,11 +301,11 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||||
HotMobiLogger.getInstance(activity).log(status.account_key, event)
|
HotMobiLogger.getInstance(activity).log(status.account_key, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onGapClick(holder: GapViewHolder, position: Int) {
|
override fun onGapClick(holder: GapViewHolder, position: Int) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onItemActionClick(holder: ViewHolder, id: Int, position: Int) {
|
override fun onItemActionClick(holder: ViewHolder, id: Int, position: Int) {
|
||||||
val status = adapter.getStatus(position)
|
val status = adapter.getStatus(position)
|
||||||
AbsStatusesFragment.handleStatusActionClick(context, fragmentManager, twitterWrapper,
|
AbsStatusesFragment.handleStatusActionClick(context, fragmentManager, twitterWrapper,
|
||||||
|
@ -398,7 +398,6 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||||
repeatCount, event, metaState)
|
repeatCount, event, metaState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateLoader(id: Int, args: Bundle): Loader<SingleResponse<ParcelableStatus>> {
|
override fun onCreateLoader(id: Int, args: Bundle): Loader<SingleResponse<ParcelableStatus>> {
|
||||||
val fragmentArgs = arguments
|
val fragmentArgs = arguments
|
||||||
val accountKey = fragmentArgs.getParcelable<UserKey>(EXTRA_ACCOUNT_KEY)
|
val accountKey = fragmentArgs.getParcelable<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||||
|
@ -406,6 +405,7 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||||
return ParcelableStatusLoader(activity, false, fragmentArgs, accountKey, statusId)
|
return ParcelableStatusLoader(activity, false, fragmentArgs, accountKey, statusId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onLoadFinished(loader: Loader<SingleResponse<ParcelableStatus>>,
|
override fun onLoadFinished(loader: Loader<SingleResponse<ParcelableStatus>>,
|
||||||
data: SingleResponse<ParcelableStatus>) {
|
data: SingleResponse<ParcelableStatus>) {
|
||||||
val activity = activity ?: return
|
val activity = activity ?: return
|
||||||
|
@ -746,7 +746,10 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DetailStatusViewHolder(private val adapter: StatusAdapter, itemView: View) : ViewHolder(itemView), OnClickListener, ActionMenuView.OnMenuItemClickListener {
|
private class DetailStatusViewHolder(
|
||||||
|
private val adapter: StatusAdapter,
|
||||||
|
itemView: View
|
||||||
|
) : ViewHolder(itemView), OnClickListener, ActionMenuView.OnMenuItemClickListener {
|
||||||
|
|
||||||
private val linkClickHandler: StatusLinkClickHandler
|
private val linkClickHandler: StatusLinkClickHandler
|
||||||
private val linkify: TwidereLinkify
|
private val linkify: TwidereLinkify
|
||||||
|
@ -1144,6 +1147,7 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||||
itemView.quotedMediaPreview.setStyle(adapter.mediaPreviewStyle)
|
itemView.quotedMediaPreview.setStyle(adapter.mediaPreviewStyle)
|
||||||
|
|
||||||
itemView.text.customSelectionActionModeCallback = StatusActionModeCallback(itemView.text, activity)
|
itemView.text.customSelectionActionModeCallback = StatusActionModeCallback(itemView.text, activity)
|
||||||
|
itemView.profileImage.style = adapter.profileImageStyle
|
||||||
|
|
||||||
val layoutManager = LinearLayoutManager(adapter.context)
|
val layoutManager = LinearLayoutManager(adapter.context)
|
||||||
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
|
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
|
||||||
|
|
|
@ -81,6 +81,7 @@ import nl.komponents.kovenant.ui.successUi
|
||||||
import org.apache.commons.lang3.ObjectUtils
|
import org.apache.commons.lang3.ObjectUtils
|
||||||
import org.mariotaku.chameleon.Chameleon
|
import org.mariotaku.chameleon.Chameleon
|
||||||
import org.mariotaku.chameleon.ChameleonUtils
|
import org.mariotaku.chameleon.ChameleonUtils
|
||||||
|
import org.mariotaku.kpreferences.get
|
||||||
import org.mariotaku.ktextension.Bundle
|
import org.mariotaku.ktextension.Bundle
|
||||||
import org.mariotaku.ktextension.empty
|
import org.mariotaku.ktextension.empty
|
||||||
import org.mariotaku.ktextension.set
|
import org.mariotaku.ktextension.set
|
||||||
|
@ -99,6 +100,7 @@ import org.mariotaku.twidere.adapter.SupportTabsAdapter
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.annotation.Referral
|
import org.mariotaku.twidere.annotation.Referral
|
||||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
||||||
|
import org.mariotaku.twidere.constant.profileImageStyleKey
|
||||||
import org.mariotaku.twidere.fragment.AbsStatusesFragment.StatusesFragmentDelegate
|
import org.mariotaku.twidere.fragment.AbsStatusesFragment.StatusesFragmentDelegate
|
||||||
import org.mariotaku.twidere.fragment.UserTimelineFragment.UserTimelineFragmentDelegate
|
import org.mariotaku.twidere.fragment.UserTimelineFragment.UserTimelineFragmentDelegate
|
||||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback
|
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback
|
||||||
|
@ -706,11 +708,13 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||||
ViewCompat.setElevation(toolbarTabs, actionBarElevation)
|
ViewCompat.setElevation(toolbarTabs, actionBarElevation)
|
||||||
|
|
||||||
setupBaseActionBar()
|
setupBaseActionBar()
|
||||||
|
setupViewStyle()
|
||||||
setupUserPages()
|
setupUserPages()
|
||||||
|
|
||||||
getUserInfo(accountId, userId, screenName, false)
|
getUserInfo(accountId, userId, screenName, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
bus.register(this)
|
bus.register(this)
|
||||||
|
@ -1332,6 +1336,11 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||||
actionBar.setBackgroundDrawable(actionBarBackground)
|
actionBar.setBackgroundDrawable(actionBarBackground)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setupViewStyle() {
|
||||||
|
profileImage.style = preferences[profileImageStyleKey]
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupUserPages() {
|
private fun setupUserPages() {
|
||||||
val args = arguments
|
val args = arguments
|
||||||
val tabArgs = Bundle()
|
val tabArgs = Bundle()
|
||||||
|
|
|
@ -24,7 +24,6 @@ import android.support.v4.view.MarginLayoutParamsCompat
|
||||||
import android.support.v7.widget.RecyclerView.ViewHolder
|
import android.support.v7.widget.RecyclerView.ViewHolder
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter
|
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter
|
||||||
|
@ -35,13 +34,17 @@ import org.mariotaku.twidere.model.ParcelableUser
|
||||||
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
|
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
|
||||||
import org.mariotaku.twidere.view.BadgeView
|
import org.mariotaku.twidere.view.BadgeView
|
||||||
import org.mariotaku.twidere.view.IconActionView
|
import org.mariotaku.twidere.view.IconActionView
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
import org.mariotaku.twidere.view.ShortTimeView
|
import org.mariotaku.twidere.view.ShortTimeView
|
||||||
import org.mariotaku.twidere.view.iface.IColorLabelView
|
import org.mariotaku.twidere.view.iface.IColorLabelView
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 15/1/3.
|
* Created by mariotaku on 15/1/3.
|
||||||
*/
|
*/
|
||||||
class ActivityTitleSummaryViewHolder(private val adapter: ParcelableActivitiesAdapter, itemView: View) : ViewHolder(itemView), View.OnClickListener {
|
class ActivityTitleSummaryViewHolder(
|
||||||
|
itemView: View,
|
||||||
|
private val adapter: ParcelableActivitiesAdapter
|
||||||
|
) : ViewHolder(itemView), View.OnClickListener {
|
||||||
|
|
||||||
private val itemContent: IColorLabelView
|
private val itemContent: IColorLabelView
|
||||||
private val activityTypeView: IconActionView
|
private val activityTypeView: IconActionView
|
||||||
|
@ -50,7 +53,7 @@ class ActivityTitleSummaryViewHolder(private val adapter: ParcelableActivitiesAd
|
||||||
private val timeView: ShortTimeView
|
private val timeView: ShortTimeView
|
||||||
private val profileImagesContainer: ViewGroup
|
private val profileImagesContainer: ViewGroup
|
||||||
private val profileImageMoreNumber: BadgeView
|
private val profileImageMoreNumber: BadgeView
|
||||||
private val profileImageViews: Array<ImageView>
|
private val profileImageViews: Array<ProfileImageView>
|
||||||
private val profileImageSpace: View
|
private val profileImageSpace: View
|
||||||
|
|
||||||
private var mActivityEventListener: IActivitiesAdapter.ActivityEventListener? = null
|
private var mActivityEventListener: IActivitiesAdapter.ActivityEventListener? = null
|
||||||
|
@ -66,11 +69,11 @@ class ActivityTitleSummaryViewHolder(private val adapter: ParcelableActivitiesAd
|
||||||
|
|
||||||
profileImagesContainer = itemView.findViewById(R.id.profile_images_container) as ViewGroup
|
profileImagesContainer = itemView.findViewById(R.id.profile_images_container) as ViewGroup
|
||||||
profileImageViews = arrayOf(
|
profileImageViews = arrayOf(
|
||||||
itemView.findViewById(R.id.activity_profile_image_0) as ImageView,
|
itemView.findViewById(R.id.activity_profile_image_0) as ProfileImageView,
|
||||||
itemView.findViewById(R.id.activity_profile_image_1) as ImageView,
|
itemView.findViewById(R.id.activity_profile_image_1) as ProfileImageView,
|
||||||
itemView.findViewById(R.id.activity_profile_image_2) as ImageView,
|
itemView.findViewById(R.id.activity_profile_image_2) as ProfileImageView,
|
||||||
itemView.findViewById(R.id.activity_profile_image_3) as ImageView,
|
itemView.findViewById(R.id.activity_profile_image_3) as ProfileImageView,
|
||||||
itemView.findViewById(R.id.activity_profile_image_4) as ImageView
|
itemView.findViewById(R.id.activity_profile_image_4) as ProfileImageView
|
||||||
)
|
)
|
||||||
profileImageMoreNumber = itemView.findViewById(R.id.activity_profile_image_more_number) as BadgeView
|
profileImageMoreNumber = itemView.findViewById(R.id.activity_profile_image_more_number) as BadgeView
|
||||||
|
|
||||||
|
@ -110,10 +113,15 @@ class ActivityTitleSummaryViewHolder(private val adapter: ParcelableActivitiesAd
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTextSize(textSize: Float) {
|
fun setupViewOptions() {
|
||||||
|
val textSize = adapter.textSize
|
||||||
titleView.textSize = textSize
|
titleView.textSize = textSize
|
||||||
summaryView.textSize = textSize * 0.85f
|
summaryView.textSize = textSize * 0.85f
|
||||||
timeView.textSize = textSize * 0.80f
|
timeView.textSize = textSize * 0.80f
|
||||||
|
|
||||||
|
profileImageViews.forEach {
|
||||||
|
it.style = adapter.profileImageStyle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun displayUserProfileImages(statuses: Array<ParcelableUser>?) {
|
private fun displayUserProfileImages(statuses: Array<ParcelableUser>?) {
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* 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.view.holder
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView.ViewHolder
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import kotlinx.android.synthetic.main.card_item_group_compact.view.*
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
|
import org.mariotaku.twidere.adapter.iface.IGroupsAdapter
|
||||||
|
import org.mariotaku.twidere.model.ParcelableGroup
|
||||||
|
import org.mariotaku.twidere.model.util.UserKeyUtils
|
||||||
|
import org.mariotaku.twidere.util.Utils
|
||||||
|
import org.mariotaku.twidere.view.ColorLabelRelativeLayout
|
||||||
|
import org.mariotaku.twidere.view.NameView
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 15/4/29.
|
||||||
|
*/
|
||||||
|
class GroupViewHolder(private val adapter: IGroupsAdapter<*>, itemView: View) : ViewHolder(itemView), View.OnClickListener, View.OnLongClickListener {
|
||||||
|
|
||||||
|
private val itemContent: ColorLabelRelativeLayout
|
||||||
|
private val profileImageView: ProfileImageView
|
||||||
|
private val nameView: NameView
|
||||||
|
private val externalIndicator: TextView
|
||||||
|
private val descriptionView: TextView
|
||||||
|
private val membersCountView: TextView
|
||||||
|
private val adminsCountView: TextView
|
||||||
|
|
||||||
|
private var groupClickListener: IGroupsAdapter.GroupAdapterListener? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemContent = itemView.itemContent
|
||||||
|
profileImageView = itemView.profileImage
|
||||||
|
nameView = itemView.name
|
||||||
|
externalIndicator = itemView.externalIndicator
|
||||||
|
descriptionView = itemView.description
|
||||||
|
membersCountView = itemView.membersCount
|
||||||
|
adminsCountView = itemView.adminsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayGroup(group: ParcelableGroup) {
|
||||||
|
val context = itemView.context
|
||||||
|
val loader = adapter.mediaLoader
|
||||||
|
val formatter = adapter.bidiFormatter
|
||||||
|
|
||||||
|
nameView.setName(group.fullname)
|
||||||
|
nameView.setScreenName("!" + group.nickname)
|
||||||
|
|
||||||
|
nameView.updateText(formatter)
|
||||||
|
val groupHost = UserKeyUtils.getUserHost(group.url, group.account_key.host)
|
||||||
|
if (UserKeyUtils.isSameHost(group.account_key.host, groupHost)) {
|
||||||
|
externalIndicator.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
externalIndicator.visibility = View.VISIBLE
|
||||||
|
externalIndicator.text = context.getString(R.string.external_group_host_format,
|
||||||
|
groupHost)
|
||||||
|
}
|
||||||
|
if (adapter.profileImageEnabled) {
|
||||||
|
profileImageView.visibility = View.VISIBLE
|
||||||
|
loader.displayProfileImage(profileImageView, group.homepage_logo)
|
||||||
|
} else {
|
||||||
|
profileImageView.visibility = View.GONE
|
||||||
|
loader.cancelDisplayTask(profileImageView)
|
||||||
|
}
|
||||||
|
descriptionView.visibility = if (TextUtils.isEmpty(group.description)) View.GONE else View.VISIBLE
|
||||||
|
descriptionView.text = formatter.unicodeWrap(group.description)
|
||||||
|
membersCountView.text = Utils.getLocalizedNumber(Locale.getDefault(), group.member_count)
|
||||||
|
adminsCountView.text = Utils.getLocalizedNumber(Locale.getDefault(), group.admin_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnClickListeners() {
|
||||||
|
setGroupClickListener(adapter.groupAdapterListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
val listener = groupClickListener ?: return
|
||||||
|
when (v.id) {
|
||||||
|
R.id.itemContent -> {
|
||||||
|
listener.onGroupClick(this, layoutPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(v: View): Boolean {
|
||||||
|
val listener = groupClickListener ?: return false
|
||||||
|
when (v.id) {
|
||||||
|
R.id.itemContent -> {
|
||||||
|
return listener.onGroupLongClick(this, layoutPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setGroupClickListener(listener: IGroupsAdapter.GroupAdapterListener?) {
|
||||||
|
groupClickListener = listener
|
||||||
|
itemContent.setOnClickListener(this)
|
||||||
|
itemContent.setOnLongClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setupViewOptions() {
|
||||||
|
profileImageView.style = adapter.profileImageStyle
|
||||||
|
setTextSize(adapter.textSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTextSize(textSize: Float) {
|
||||||
|
descriptionView.textSize = textSize
|
||||||
|
externalIndicator.textSize = textSize
|
||||||
|
nameView.setPrimaryTextSize(textSize)
|
||||||
|
nameView.setSecondaryTextSize(textSize * 0.75f)
|
||||||
|
membersCountView.textSize = textSize
|
||||||
|
adminsCountView.textSize = textSize
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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.view.holder
|
||||||
|
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.view.View
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
|
import org.mariotaku.twidere.adapter.MessageConversationAdapter
|
||||||
|
import org.mariotaku.twidere.model.ParcelableDirectMessageCursorIndices
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 15/4/25.
|
||||||
|
*/
|
||||||
|
class IncomingMessageViewHolder(
|
||||||
|
adapter: MessageConversationAdapter,
|
||||||
|
itemView: View
|
||||||
|
) : MessageViewHolder(adapter, itemView) {
|
||||||
|
|
||||||
|
private val profileImageView = itemView.findViewById(R.id.profileImage) as ProfileImageView
|
||||||
|
|
||||||
|
init {
|
||||||
|
profileImageView.style = adapter.profileImageStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun displayMessage(cursor: Cursor, indices: ParcelableDirectMessageCursorIndices) {
|
||||||
|
super.displayMessage(cursor, indices)
|
||||||
|
val wrapper = adapter.mediaLoader
|
||||||
|
if (adapter.profileImageEnabled) {
|
||||||
|
profileImageView.visibility = View.VISIBLE
|
||||||
|
wrapper.displayProfileImage(profileImageView, cursor.getString(indices.sender_profile_image_url))
|
||||||
|
} else {
|
||||||
|
profileImageView.visibility = View.GONE
|
||||||
|
wrapper.cancelDisplayTask(profileImageView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* 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.holder
|
||||||
|
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.support.annotation.UiThread
|
||||||
|
import android.support.v7.widget.RecyclerView.ViewHolder
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.OnClickListener
|
||||||
|
import android.widget.TextView
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
|
import org.mariotaku.twidere.adapter.MessageEntriesAdapter
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries
|
||||||
|
import org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText
|
||||||
|
import org.mariotaku.twidere.view.NameView
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
|
import org.mariotaku.twidere.view.ShortTimeView
|
||||||
|
import org.mariotaku.twidere.view.iface.IColorLabelView
|
||||||
|
|
||||||
|
class MessageEntryViewHolder(private val adapter: MessageEntriesAdapter, itemView: View) : ViewHolder(itemView), OnClickListener {
|
||||||
|
|
||||||
|
val profileImageView: ProfileImageView
|
||||||
|
val nameView: NameView
|
||||||
|
val textView: TextView
|
||||||
|
val timeView: ShortTimeView
|
||||||
|
private val content: IColorLabelView
|
||||||
|
|
||||||
|
init {
|
||||||
|
content = itemView.findViewById(R.id.content) as IColorLabelView
|
||||||
|
profileImageView = itemView.findViewById(R.id.profileImage) as ProfileImageView
|
||||||
|
nameView = itemView.findViewById(R.id.name) as NameView
|
||||||
|
textView = itemView.findViewById(R.id.text) as TextView
|
||||||
|
timeView = itemView.findViewById(R.id.time) as ShortTimeView
|
||||||
|
|
||||||
|
profileImageView.style = adapter.profileImageStyle
|
||||||
|
setTextSize(adapter.textSize)
|
||||||
|
itemView.setOnClickListener(this)
|
||||||
|
profileImageView.setOnClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun displayMessage(cursor: Cursor, isUnread: Boolean) {
|
||||||
|
val context = adapter.context
|
||||||
|
val loader = adapter.mediaLoader
|
||||||
|
val manager = adapter.userColorNameManager
|
||||||
|
|
||||||
|
val accountKey = UserKey.valueOf(cursor.getString(ConversationEntries.IDX_ACCOUNT_KEY))
|
||||||
|
val conversationId = UserKey.valueOf(cursor.getString(ConversationEntries.IDX_CONVERSATION_ID))
|
||||||
|
val timestamp = cursor.getLong(ConversationEntries.IDX_MESSAGE_TIMESTAMP)
|
||||||
|
val isOutgoing = cursor.getInt(ConversationEntries.IDX_IS_OUTGOING) == 1
|
||||||
|
|
||||||
|
val name = cursor.getString(ConversationEntries.IDX_NAME)
|
||||||
|
val screenName = cursor.getString(ConversationEntries.IDX_SCREEN_NAME)
|
||||||
|
|
||||||
|
nameView.setName(manager.getUserNickname(conversationId, name))
|
||||||
|
nameView.setScreenName("@" + screenName)
|
||||||
|
nameView.updateText(adapter.bidiFormatter)
|
||||||
|
textView.text = toPlainText(cursor.getString(ConversationEntries.IDX_TEXT_UNESCAPED))
|
||||||
|
timeView.setTime(timestamp)
|
||||||
|
if (isOutgoing) {
|
||||||
|
timeView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_indicator_sent, 0)
|
||||||
|
} else {
|
||||||
|
timeView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
nameView.setTypeface(null, if (isUnread && !isOutgoing) Typeface.BOLD else Typeface.NORMAL)
|
||||||
|
textView.setTypeface(null, if (isUnread && !isOutgoing) Typeface.BOLD else Typeface.NORMAL)
|
||||||
|
if (adapter.shouldShowAccountsColor()) {
|
||||||
|
// FIXME draw account color
|
||||||
|
} else {
|
||||||
|
content.drawEnd()
|
||||||
|
}
|
||||||
|
content.drawStart(manager.getUserColor(conversationId))
|
||||||
|
|
||||||
|
val profileImage = cursor.getString(ConversationEntries.IDX_PROFILE_IMAGE_URL)
|
||||||
|
loader.displayProfileImage(this.profileImageView, profileImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
when (v) {
|
||||||
|
profileImageView -> {
|
||||||
|
adapter.onUserProfileClick(layoutPosition)
|
||||||
|
}
|
||||||
|
itemView -> {
|
||||||
|
adapter.onMessageClick(layoutPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTextSize(textSize: Float) {
|
||||||
|
nameView.setPrimaryTextSize(textSize * 1.1f)
|
||||||
|
nameView.setSecondaryTextSize(textSize)
|
||||||
|
textView.textSize = textSize
|
||||||
|
timeView.textSize = textSize * 0.85f
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* 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.holder
|
||||||
|
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.support.v7.widget.RecyclerView.ViewHolder
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import org.mariotaku.messagebubbleview.library.MessageBubbleView
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
|
import org.mariotaku.twidere.adapter.MessageConversationAdapter
|
||||||
|
import org.mariotaku.twidere.model.ParcelableDirectMessageCursorIndices
|
||||||
|
import org.mariotaku.twidere.model.ParcelableMedia
|
||||||
|
import org.mariotaku.twidere.model.SpanItem
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
||||||
|
import org.mariotaku.twidere.util.JsonSerializer
|
||||||
|
import org.mariotaku.twidere.util.ThemeUtils
|
||||||
|
import org.mariotaku.twidere.util.TwidereColorUtils
|
||||||
|
import org.mariotaku.twidere.util.Utils
|
||||||
|
import org.mariotaku.twidere.view.CardMediaContainer
|
||||||
|
|
||||||
|
open class MessageViewHolder(
|
||||||
|
protected val adapter: MessageConversationAdapter,
|
||||||
|
itemView: View
|
||||||
|
) : ViewHolder(itemView) {
|
||||||
|
|
||||||
|
val mediaContainer: CardMediaContainer
|
||||||
|
val textView: TextView
|
||||||
|
val time: TextView
|
||||||
|
|
||||||
|
private val messageContent: MessageBubbleView
|
||||||
|
|
||||||
|
private val textColorPrimary: Int
|
||||||
|
private val textColorPrimaryInverse: Int
|
||||||
|
private val textColorSecondary: Int
|
||||||
|
private val textColorSecondaryInverse: Int
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
val context = itemView.context
|
||||||
|
val a = context.obtainStyledAttributes(R.styleable.MessageViewHolder)
|
||||||
|
textColorPrimary = a.getColor(R.styleable.MessageViewHolder_android_textColorPrimary, 0)
|
||||||
|
textColorPrimaryInverse = a.getColor(R.styleable.MessageViewHolder_android_textColorPrimaryInverse, 0)
|
||||||
|
textColorSecondary = a.getColor(R.styleable.MessageViewHolder_android_textColorSecondary, 0)
|
||||||
|
textColorSecondaryInverse = a.getColor(R.styleable.MessageViewHolder_android_textColorSecondaryInverse, 0)
|
||||||
|
a.recycle()
|
||||||
|
messageContent = itemView.findViewById(R.id.messageContent) as MessageBubbleView
|
||||||
|
messageContent.setOnLongClickListener {
|
||||||
|
itemView.parent.showContextMenuForChild(itemView)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
messageContent.setOnClickListener { itemView.parent.showContextMenuForChild(itemView) }
|
||||||
|
textView = itemView.findViewById(R.id.text) as TextView
|
||||||
|
time = itemView.findViewById(R.id.time) as TextView
|
||||||
|
mediaContainer = itemView.findViewById(R.id.media_preview_container) as CardMediaContainer
|
||||||
|
mediaContainer.setStyle(adapter.mediaPreviewStyle)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun displayMessage(cursor: Cursor, indices: ParcelableDirectMessageCursorIndices) {
|
||||||
|
val context = adapter.context
|
||||||
|
val linkify = adapter.linkify
|
||||||
|
val loader = adapter.mediaLoader
|
||||||
|
|
||||||
|
val accountKey = UserKey.valueOf(cursor.getString(indices.account_key))
|
||||||
|
val timestamp = cursor.getLong(indices.timestamp)
|
||||||
|
val media = JsonSerializer.parseArray(cursor.getString(indices.media),
|
||||||
|
ParcelableMedia::class.java)
|
||||||
|
val spans = JsonSerializer.parseArray(cursor.getString(indices.spans),
|
||||||
|
SpanItem::class.java)
|
||||||
|
val text = SpannableStringBuilder.valueOf(cursor.getString(indices.text_unescaped))
|
||||||
|
ParcelableStatusUtils.applySpans(text, spans)
|
||||||
|
// Detect entity support
|
||||||
|
linkify.applyAllLinks(text, accountKey, false, true)
|
||||||
|
textView.text = text
|
||||||
|
time.text = Utils.formatToLongTimeString(context, timestamp)
|
||||||
|
mediaContainer.visibility = if (media != null && media.isNotEmpty()) View.VISIBLE else View.GONE
|
||||||
|
mediaContainer.displayMedia(loader, media, accountKey, adapter.onMediaClickListener, adapter.mediaLoadingHandler, layoutPosition.toLong(), true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setMessageColor(color: Int) {
|
||||||
|
val colorStateList = ColorStateList.valueOf(color)
|
||||||
|
messageContent.bubbleColor = colorStateList
|
||||||
|
val textLuminancePrimary = TwidereColorUtils.getYIQLuminance(textColorPrimary)
|
||||||
|
val textPrimaryDark: Int
|
||||||
|
val textPrimaryLight: Int
|
||||||
|
val textSecondaryDark: Int
|
||||||
|
val textSecondaryLight: Int
|
||||||
|
if (textLuminancePrimary < 128) {
|
||||||
|
textPrimaryDark = textColorPrimary
|
||||||
|
textPrimaryLight = textColorPrimaryInverse
|
||||||
|
textSecondaryDark = textColorSecondary
|
||||||
|
textSecondaryLight = textColorSecondaryInverse
|
||||||
|
} else {
|
||||||
|
textPrimaryDark = textColorPrimaryInverse
|
||||||
|
textPrimaryLight = textColorPrimary
|
||||||
|
textSecondaryDark = textColorSecondaryInverse
|
||||||
|
textSecondaryLight = textColorSecondary
|
||||||
|
}
|
||||||
|
val textContrastPrimary = TwidereColorUtils.getContrastYIQ(color,
|
||||||
|
ThemeUtils.ACCENT_COLOR_THRESHOLD, textPrimaryDark, textPrimaryLight)
|
||||||
|
val textContrastSecondary = TwidereColorUtils.getContrastYIQ(color,
|
||||||
|
ThemeUtils.ACCENT_COLOR_THRESHOLD, textSecondaryDark, textSecondaryLight)
|
||||||
|
textView.setTextColor(textContrastPrimary)
|
||||||
|
textView.setLinkTextColor(textContrastSecondary)
|
||||||
|
time.setTextColor(textContrastSecondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTextSize(textSize: Float) {
|
||||||
|
textView.textSize = textSize
|
||||||
|
time.textSize = textSize * 0.75f
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
||||||
import org.mariotaku.twidere.util.*
|
import org.mariotaku.twidere.util.*
|
||||||
import org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText
|
import org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText
|
||||||
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
|
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ import java.lang.ref.WeakReference
|
||||||
*/
|
*/
|
||||||
class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : ViewHolder(itemView), Constants, IStatusViewHolder {
|
class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : ViewHolder(itemView), Constants, IStatusViewHolder {
|
||||||
|
|
||||||
override val profileImageView: ImageView by lazy { itemView.profileImage }
|
override val profileImageView: ProfileImageView by lazy { itemView.profileImage }
|
||||||
override val profileTypeView: ImageView by lazy { itemView.profileType }
|
override val profileTypeView: ImageView by lazy { itemView.profileType }
|
||||||
|
|
||||||
private val itemContent by lazy { itemView.itemContent }
|
private val itemContent by lazy { itemView.itemContent }
|
||||||
|
@ -460,6 +461,8 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
|
||||||
|
|
||||||
fun setupViewOptions() {
|
fun setupViewOptions() {
|
||||||
setTextSize(adapter.textSize)
|
setTextSize(adapter.textSize)
|
||||||
|
profileImageView.style = adapter.profileImageStyle
|
||||||
|
|
||||||
mediaPreview.setStyle(adapter.mediaPreviewStyle)
|
mediaPreview.setStyle(adapter.mediaPreviewStyle)
|
||||||
quotedMediaPreview.setStyle(adapter.mediaPreviewStyle)
|
quotedMediaPreview.setStyle(adapter.mediaPreviewStyle)
|
||||||
// profileImageView.setStyle(adapter.getProfileImageStyle());
|
// profileImageView.setStyle(adapter.getProfileImageStyle());
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* 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.view.holder
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView.ViewHolder
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import kotlinx.android.synthetic.main.list_item_user_list.view.*
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
|
import org.mariotaku.twidere.adapter.iface.IUserListsAdapter
|
||||||
|
import org.mariotaku.twidere.model.ParcelableUserList
|
||||||
|
import org.mariotaku.twidere.util.Utils
|
||||||
|
import org.mariotaku.twidere.view.ColorLabelRelativeLayout
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 15/4/29.
|
||||||
|
*/
|
||||||
|
class UserListViewHolder(
|
||||||
|
itemView: View,
|
||||||
|
private val adapter: IUserListsAdapter<*>
|
||||||
|
) : ViewHolder(itemView), View.OnClickListener, View.OnLongClickListener {
|
||||||
|
|
||||||
|
private val itemContent: ColorLabelRelativeLayout
|
||||||
|
private val profileImageView: ProfileImageView
|
||||||
|
private val nameView: TextView
|
||||||
|
private val createdByView: TextView
|
||||||
|
private val descriptionView: TextView
|
||||||
|
private val membersCountView: TextView
|
||||||
|
private val subscribersCountView: TextView
|
||||||
|
|
||||||
|
private var userListClickListener: IUserListsAdapter.UserListClickListener? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemContent = itemView.itemContent
|
||||||
|
profileImageView = itemView.profileImage
|
||||||
|
nameView = itemView.name
|
||||||
|
createdByView = itemView.createdBy
|
||||||
|
descriptionView = itemView.description
|
||||||
|
membersCountView = itemView.membersCount
|
||||||
|
subscribersCountView = itemView.subscribersCount
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayUserList(userList: ParcelableUserList) {
|
||||||
|
val context = itemView.context
|
||||||
|
val loader = adapter.mediaLoader
|
||||||
|
val manager = adapter.userColorNameManager
|
||||||
|
|
||||||
|
itemContent.drawStart(manager.getUserColor(userList.user_key))
|
||||||
|
nameView.text = userList.name
|
||||||
|
val nameFirst = adapter.nameFirst
|
||||||
|
val createdByDisplayName = manager.getDisplayName(userList, nameFirst)
|
||||||
|
createdByView.text = context.getString(R.string.created_by, createdByDisplayName)
|
||||||
|
|
||||||
|
if (adapter.profileImageEnabled) {
|
||||||
|
profileImageView.visibility = View.VISIBLE
|
||||||
|
loader.displayProfileImage(profileImageView, userList.user_profile_image_url)
|
||||||
|
} else {
|
||||||
|
profileImageView.visibility = View.GONE
|
||||||
|
loader.cancelDisplayTask(profileImageView)
|
||||||
|
}
|
||||||
|
descriptionView.visibility = if (TextUtils.isEmpty(userList.description)) View.GONE else View.VISIBLE
|
||||||
|
descriptionView.text = userList.description
|
||||||
|
membersCountView.text = Utils.getLocalizedNumber(Locale.getDefault(), userList.members_count)
|
||||||
|
subscribersCountView.text = Utils.getLocalizedNumber(Locale.getDefault(), userList.subscribers_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnClickListeners() {
|
||||||
|
setUserListClickListener(adapter.userListClickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
val listener = userListClickListener ?: return
|
||||||
|
when (v.id) {
|
||||||
|
R.id.itemContent -> {
|
||||||
|
listener.onUserListClick(this, layoutPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(v: View): Boolean {
|
||||||
|
val listener = userListClickListener ?: return false
|
||||||
|
when (v.id) {
|
||||||
|
R.id.itemContent -> {
|
||||||
|
return listener.onUserListLongClick(this, layoutPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUserListClickListener(listener: IUserListsAdapter.UserListClickListener?) {
|
||||||
|
userListClickListener = listener
|
||||||
|
itemContent.setOnClickListener(this)
|
||||||
|
itemContent.setOnLongClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setupViewOptions() {
|
||||||
|
profileImageView.style = adapter.profileImageStyle
|
||||||
|
setTextSize(adapter.textSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTextSize(textSize: Float) {
|
||||||
|
nameView.textSize = textSize
|
||||||
|
createdByView.textSize = textSize * 0.75f
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import org.mariotaku.twidere.model.util.UserKeyUtils
|
||||||
import org.mariotaku.twidere.util.Utils
|
import org.mariotaku.twidere.util.Utils
|
||||||
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
|
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
|
||||||
import org.mariotaku.twidere.view.NameView
|
import org.mariotaku.twidere.view.NameView
|
||||||
|
import org.mariotaku.twidere.view.ProfileImageView
|
||||||
import org.mariotaku.twidere.view.iface.IColorLabelView
|
import org.mariotaku.twidere.view.iface.IColorLabelView
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ class UserViewHolder(
|
||||||
) : ViewHolder(itemView), OnClickListener, OnLongClickListener {
|
) : ViewHolder(itemView), OnClickListener, OnLongClickListener {
|
||||||
|
|
||||||
private val itemContent: IColorLabelView
|
private val itemContent: IColorLabelView
|
||||||
val profileImageView: ImageView
|
val profileImageView: ProfileImageView
|
||||||
val profileTypeView: ImageView
|
val profileTypeView: ImageView
|
||||||
private val nameView: NameView
|
private val nameView: NameView
|
||||||
private val externalIndicator: TextView
|
private val externalIndicator: TextView
|
||||||
|
@ -270,6 +271,7 @@ class UserViewHolder(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setupViewOptions() {
|
fun setupViewOptions() {
|
||||||
|
profileImageView.style = adapter.profileImageStyle
|
||||||
setTextSize(adapter.textSize)
|
setTextSize(adapter.textSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
android:layout_width="@dimen/icon_size_list_item_small"
|
android:layout_width="@dimen/icon_size_list_item_small"
|
||||||
android:layout_height="@dimen/icon_size_list_item_small"
|
android:layout_height="@dimen/icon_size_list_item_small"
|
||||||
android:contentDescription="@string/icon"
|
android:contentDescription="@string/icon"
|
||||||
android:scaleType="fitCenter" />
|
android:scaleType="fitCenter"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -47,15 +48,15 @@
|
||||||
android:id="@android:id/text1"
|
android:id="@android:id/text1"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:maxLines="1"
|
||||||
android:maxLines="1"/>
|
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@android:id/text2"
|
android:id="@android:id/text2"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:maxLines="1"
|
||||||
android:maxLines="1"/>
|
android:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -33,7 +33,7 @@
|
||||||
app:ignorePadding="true"
|
app:ignorePadding="true"
|
||||||
tools:context=".adapter.MessageEntriesAdapter">
|
tools:context=".adapter.MessageEntriesAdapter">
|
||||||
|
|
||||||
<org.mariotaku.twidere.view.ShapedImageView
|
<org.mariotaku.twidere.view.ProfileImageView
|
||||||
android:id="@+id/profileImage"
|
android:id="@+id/profileImage"
|
||||||
style="?profileImageStyle"
|
style="?profileImageStyle"
|
||||||
android:layout_width="@dimen/icon_size_card_list_item"
|
android:layout_width="@dimen/icon_size_card_list_item"
|
||||||
|
@ -86,9 +86,9 @@
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:drawablePadding="4dp"
|
android:drawablePadding="4dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
tools:text="12:00"
|
tools:text="12:00"/>
|
||||||
android:maxLines="1"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
|
@ -98,9 +98,9 @@
|
||||||
android:layout_alignStart="@+id/name"
|
android:layout_alignStart="@+id/name"
|
||||||
android:layout_below="@+id/name"
|
android:layout_below="@+id/name"
|
||||||
android:layout_marginTop="@dimen/element_spacing_xsmall"
|
android:layout_marginTop="@dimen/element_spacing_xsmall"
|
||||||
|
android:maxLines="1"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
tools:text="@string/sample_status_text"
|
tools:text="@string/sample_status_text"/>
|
||||||
android:maxLines="1"/>
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</org.mariotaku.twidere.view.ColorLabelRelativeLayout>
|
</org.mariotaku.twidere.view.ColorLabelRelativeLayout>
|
Loading…
Reference in New Issue