mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-07 23:38:40 +01:00
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.OnSharedPreferenceChangeListener;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
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.widget.SwitchCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
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.R;
|
||||
import org.mariotaku.twidere.model.AccountDetails;
|
||||
import org.mariotaku.twidere.model.util.AccountUtils;
|
||||
import org.mariotaku.twidere.util.BitmapUtils;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
||||
|
||||
@ -101,8 +94,7 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
|
||||
return mSwitchDefault;
|
||||
}
|
||||
|
||||
public static final class AccountItemPreference extends Preference implements ImageLoadingListener,
|
||||
OnSharedPreferenceChangeListener {
|
||||
public static final class AccountItemPreference extends Preference implements OnSharedPreferenceChangeListener {
|
||||
|
||||
private final AccountDetails mAccount;
|
||||
@Nullable
|
||||
@ -125,33 +117,9 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
|
||||
mSwitchPreference.registerOnSharedPreferenceChangeListener(this);
|
||||
setTitle(mAccount.user.name);
|
||||
setSummary(String.format("@%s", mAccount.user.screen_name));
|
||||
mImageLoader.loadProfileImage(mAccount, this);
|
||||
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
|
||||
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
|
||||
notifyChanged();
|
||||
|
@ -17,15 +17,7 @@
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.graphics.Bitmap;
|
||||
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.support.annotation.Nullable;
|
||||
|
||||
@ -38,27 +30,6 @@ public class 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
|
||||
public static String getImageMimeType(ContentResolver cr, final Uri uri) {
|
||||
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()) {
|
||||
MenuUtils.addIntentToMenu(this, mediaMenuItem.subMenu, imageExtensionsIntent, MENU_GROUP_IMAGE_EXTENSION)
|
||||
}
|
||||
updateViewStyle()
|
||||
setMenu()
|
||||
updateLocationState()
|
||||
notifyAccountSelectionChanged()
|
||||
@ -633,6 +634,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
||||
updateAttachedMediaView()
|
||||
}
|
||||
|
||||
private fun updateViewStyle() {
|
||||
accountProfileImage.style = preferences[profileImageStyleKey]
|
||||
}
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
val keyCode = event.keyCode
|
||||
if (KeyEvent.isModifierKey(keyCode)) {
|
||||
|
@ -19,35 +19,22 @@
|
||||
|
||||
package org.mariotaku.twidere.adapter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.list_item_simple_user.view.*
|
||||
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.UserKey
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
class AccountsSpinnerAdapter(
|
||||
context: Context,
|
||||
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
|
||||
|
||||
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) {
|
||||
addAll(accounts)
|
||||
}
|
||||
@ -73,34 +60,26 @@ class AccountsSpinnerAdapter(
|
||||
val text2 = view.screenName
|
||||
val icon = view.profileImage
|
||||
if (!item.dummy) {
|
||||
if (text1 != null) {
|
||||
text1.visibility = View.VISIBLE
|
||||
text1.text = item.user.name
|
||||
}
|
||||
if (text2 != null) {
|
||||
text2.visibility = View.VISIBLE
|
||||
text2.text = String.format("@%s", item.user.screen_name)
|
||||
}
|
||||
text1?.visibility = View.VISIBLE
|
||||
text1?.text = item.user.name
|
||||
text2?.visibility = View.VISIBLE
|
||||
@SuppressLint("SetTextI18n")
|
||||
text2?.text = "@${item.user.screen_name}"
|
||||
if (icon != null) {
|
||||
icon.visibility = View.VISIBLE
|
||||
if (displayProfileImage) {
|
||||
if (profileImageEnabled) {
|
||||
icon.visibility = View.VISIBLE
|
||||
icon.style = profileImageStyle
|
||||
mediaLoader.displayProfileImage(icon, item.user)
|
||||
} else {
|
||||
icon.visibility = View.GONE
|
||||
mediaLoader.cancelDisplayTask(icon)
|
||||
// icon.setImageResource(R.drawable.ic_profile_image_default);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (text1 != null) {
|
||||
text1.visibility = View.VISIBLE
|
||||
text1.text = dummyItemText
|
||||
}
|
||||
if (text2 != null) {
|
||||
text2.visibility = View.GONE
|
||||
}
|
||||
if (icon != null) {
|
||||
icon.visibility = View.GONE
|
||||
}
|
||||
text1?.visibility = View.VISIBLE
|
||||
text1?.text = dummyItemText
|
||||
text2?.visibility = View.GONE
|
||||
icon?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,10 @@ open class BaseArrayAdapter<T>(
|
||||
@Inject
|
||||
lateinit var preferences: SharedPreferencesWrapper
|
||||
|
||||
override val profileImageStyle: Int
|
||||
override val textSize: Float
|
||||
override val profileImageEnabled: Boolean
|
||||
override val isShowAbsoluteTime: Boolean
|
||||
final override val profileImageStyle: Int
|
||||
final override val textSize: Float
|
||||
final override val profileImageEnabled: Boolean
|
||||
final override val isShowAbsoluteTime: Boolean
|
||||
val nameFirst: Boolean
|
||||
|
||||
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 -> {
|
||||
val view = inflater.inflate(R.layout.card_item_activity_summary_compact, parent, false)
|
||||
val holder = ActivityTitleSummaryViewHolder(this,
|
||||
view)
|
||||
val holder = ActivityTitleSummaryViewHolder(view, this)
|
||||
holder.setOnClickListeners()
|
||||
holder.setTextSize(textSize)
|
||||
holder.setupViewOptions()
|
||||
return holder
|
||||
}
|
||||
ITEM_VIEW_TYPE_GAP -> {
|
||||
|
@ -63,7 +63,7 @@ class ParcelableGroupsAdapter(context: Context) : LoadMoreSupportAdapter<Recycle
|
||||
}
|
||||
|
||||
private fun bindGroup(holder: GroupViewHolder, position: Int) {
|
||||
holder.displayGroup(getGroup(position))
|
||||
holder.displayGroup(getGroup(position)!!)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
|
@ -22,7 +22,6 @@ package org.mariotaku.twidere.adapter
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.twidere.R
|
||||
@ -37,19 +36,14 @@ import org.mariotaku.twidere.view.holder.UserListViewHolder
|
||||
class ParcelableUserListsAdapter(
|
||||
context: Context
|
||||
) : LoadMoreSupportAdapter<RecyclerView.ViewHolder>(context), IUserListsAdapter<List<ParcelableUserList>> {
|
||||
override val showAccountsColor: Boolean
|
||||
get() = false
|
||||
override val nameFirst: Boolean
|
||||
override val showAccountsColor: Boolean = false
|
||||
override val nameFirst: Boolean = preferences[nameFirstKey]
|
||||
override var userListClickListener: IUserListsAdapter.UserListClickListener? = null
|
||||
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
private var data: List<ParcelableUserList>? = null
|
||||
|
||||
|
||||
init {
|
||||
nameFirst = preferences[nameFirstKey]
|
||||
}
|
||||
|
||||
fun getData(): List<ParcelableUserList>? {
|
||||
return data
|
||||
}
|
||||
@ -62,7 +56,7 @@ class ParcelableUserListsAdapter(
|
||||
}
|
||||
|
||||
private fun bindUserList(holder: UserListViewHolder, position: Int) {
|
||||
holder.displayUserList(getUserList(position))
|
||||
holder.displayUserList(getUserList(position)!!)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
@ -131,9 +125,8 @@ class ParcelableUserListsAdapter(
|
||||
fun createUserListViewHolder(adapter: IUserListsAdapter<*>,
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup): UserListViewHolder {
|
||||
val view: View
|
||||
view = inflater.inflate(R.layout.list_item_user_list, parent, false)
|
||||
val holder = UserListViewHolder(adapter, view)
|
||||
val view = inflater.inflate(R.layout.list_item_user_list, parent, false)
|
||||
val holder = UserListViewHolder(view, adapter)
|
||||
holder.setOnClickListeners()
|
||||
holder.setupViewOptions()
|
||||
return holder
|
||||
|
@ -19,19 +19,22 @@
|
||||
|
||||
package org.mariotaku.twidere.adapter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.support.v4.widget.SimpleCursorAdapter
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.sqliteqb.library.Columns
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.sqliteqb.library.OrderBy
|
||||
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.provider.TwidereDataStore.CachedUsers
|
||||
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.Utils
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||
import org.mariotaku.twidere.view.ProfileImageView
|
||||
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
|
||||
lateinit var profileImageLoader: MediaLoaderWrapper
|
||||
@Inject
|
||||
lateinit var mPreferences: SharedPreferencesWrapper
|
||||
lateinit var preferences: SharedPreferencesWrapper
|
||||
@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 mNameIdx: Int = 0
|
||||
private var mScreenNameIdx: Int = 0
|
||||
private var mProfileImageIdx: Int = 0
|
||||
private var mAccountKey: UserKey? = null
|
||||
private var indices: ParcelableUserCursorIndices? = null
|
||||
|
||||
private var accountKey: UserKey? = null
|
||||
|
||||
init {
|
||||
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) {
|
||||
val indices = this.indices!!
|
||||
val text1 = view.findViewById(android.R.id.text1) as TextView
|
||||
val text2 = view.findViewById(android.R.id.text2) as TextView
|
||||
val 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.setImageDrawable(null)
|
||||
icon.style = profileImageStyle
|
||||
|
||||
text1.text = mUserColorNameManager.getUserNickname(cursor.getString(mIdIdx), cursor.getString(mNameIdx))
|
||||
text2.text = String.format("@%s", cursor.getString(mScreenNameIdx))
|
||||
if (mDisplayProfileImage) {
|
||||
val profileImageUrl = cursor.getString(mProfileImageIdx)
|
||||
text1.text = userColorNameManager.getUserNickname(cursor.getString(indices.key), cursor.getString(indices.name))
|
||||
@SuppressLint("SetTextI18n")
|
||||
text2.text = "@${cursor.getString(indices.screen_name)}"
|
||||
if (displayProfileImage) {
|
||||
val profileImageUrl = cursor.getString(indices.profile_image_url)
|
||||
profileImageLoader.displayProfileImage(icon, profileImageUrl)
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -93,7 +100,7 @@ class UserAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context, R
|
||||
}
|
||||
|
||||
override fun convertToString(cursor: Cursor?): CharSequence {
|
||||
return cursor!!.getString(mScreenNameIdx)
|
||||
return cursor!!.getString(indices!!.screen_name)
|
||||
}
|
||||
|
||||
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
|
||||
@ -102,7 +109,7 @@ class UserAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context, R
|
||||
if (filter != null) return filter.runQuery(constraint)
|
||||
val query = constraint.toString()
|
||||
val queryEscaped = query.replace("_", "^_")
|
||||
val nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager)
|
||||
val nicknameKeys = Utils.getMatchedNicknameKeys(query, userColorNameManager)
|
||||
val usersSelection = Expression.or(
|
||||
Expression.likeRaw(Columns.Column(CachedUsers.SCREEN_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 ascending = booleanArrayOf(false, false, true, true)
|
||||
val orderBy = OrderBy(order, ascending)
|
||||
val uri = Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, mAccountKey.toString())
|
||||
return mContext.contentResolver.query(uri, CachedUsers.COLUMNS, usersSelection.sql,
|
||||
val uri = Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, accountKey.toString())
|
||||
@SuppressLint("Recycle")
|
||||
val cursor = context.contentResolver.query(uri, CachedUsers.COLUMNS, usersSelection.sql,
|
||||
selectionArgs, orderBy.sql)
|
||||
return cursor
|
||||
}
|
||||
|
||||
|
||||
fun setAccountKey(accountKey: UserKey) {
|
||||
mAccountKey = accountKey
|
||||
this.accountKey = accountKey
|
||||
}
|
||||
|
||||
override fun swapCursor(cursor: Cursor?): Cursor? {
|
||||
if (cursor != null) {
|
||||
mIdIdx = cursor.getColumnIndex(CachedUsers.USER_KEY)
|
||||
mNameIdx = cursor.getColumnIndex(CachedUsers.NAME)
|
||||
mScreenNameIdx = cursor.getColumnIndex(CachedUsers.SCREEN_NAME)
|
||||
mProfileImageIdx = cursor.getColumnIndex(CachedUsers.PROFILE_IMAGE_URL)
|
||||
indices = ParcelableUserCursorIndices(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.widget.ImageView
|
||||
import kotlinx.android.synthetic.main.header_drawer_account_selector.view.*
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
|
||||
import org.mariotaku.ktextension.convert
|
||||
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.Referral
|
||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
||||
import org.mariotaku.twidere.constant.profileImageStyleKey
|
||||
import org.mariotaku.twidere.extension.model.setActivated
|
||||
import org.mariotaku.twidere.fragment.AccountsDashboardFragment.AccountsInfo
|
||||
import org.mariotaku.twidere.menu.AccountToggleProvider
|
||||
@ -159,7 +161,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||
})
|
||||
|
||||
profileContainer.setOnClickListener(this)
|
||||
|
||||
accountProfileImageView.style = preferences[profileImageStyleKey]
|
||||
accountProfileBanner.setInAnimation(context, android.R.anim.fade_in)
|
||||
accountProfileBanner.setOutAnimation(context, android.R.anim.fade_out)
|
||||
accountProfileBanner.setFactory {
|
||||
@ -574,13 +576,17 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||
|
||||
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
|
||||
|
||||
init {
|
||||
itemView.setOnClickListener(this)
|
||||
iconView = itemView.findViewById(android.R.id.icon) as ShapedImageView
|
||||
iconView.style = adapter.profileImageStyle
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
@ -593,7 +599,9 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||
private val inflater: LayoutInflater,
|
||||
private val fragment: AccountsDashboardFragment
|
||||
) : RecyclerPagerAdapter() {
|
||||
private val mediaLoader: MediaLoaderWrapper
|
||||
|
||||
internal var profileImageStyle: Int = fragment.preferences[profileImageStyleKey]
|
||||
internal var mediaLoader: MediaLoaderWrapper = fragment.mediaLoader
|
||||
|
||||
var accounts: Array<AccountDetails>? = null
|
||||
set(value) {
|
||||
@ -619,9 +627,6 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
|
||||
notifyPagesChanged(invalidateCache = true)
|
||||
}
|
||||
|
||||
init {
|
||||
mediaLoader = fragment.mediaLoader
|
||||
}
|
||||
|
||||
fun getAdapterAccount(position: Int): AccountDetails? {
|
||||
return accounts?.getOrNull(position - accountStart + 1)
|
||||
|
@ -301,11 +301,11 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||
HotMobiLogger.getInstance(activity).log(status.account_key, event)
|
||||
}
|
||||
|
||||
|
||||
override fun onGapClick(holder: GapViewHolder, position: Int) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun onItemActionClick(holder: ViewHolder, id: Int, position: Int) {
|
||||
val status = adapter.getStatus(position)
|
||||
AbsStatusesFragment.handleStatusActionClick(context, fragmentManager, twitterWrapper,
|
||||
@ -398,7 +398,6 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||
repeatCount, event, metaState)
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle): Loader<SingleResponse<ParcelableStatus>> {
|
||||
val fragmentArgs = arguments
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
override fun onLoadFinished(loader: Loader<SingleResponse<ParcelableStatus>>,
|
||||
data: SingleResponse<ParcelableStatus>) {
|
||||
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 linkify: TwidereLinkify
|
||||
@ -1144,6 +1147,7 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
||||
itemView.quotedMediaPreview.setStyle(adapter.mediaPreviewStyle)
|
||||
|
||||
itemView.text.customSelectionActionModeCallback = StatusActionModeCallback(itemView.text, activity)
|
||||
itemView.profileImage.style = adapter.profileImageStyle
|
||||
|
||||
val layoutManager = LinearLayoutManager(adapter.context)
|
||||
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
|
||||
|
@ -81,6 +81,7 @@ import nl.komponents.kovenant.ui.successUi
|
||||
import org.apache.commons.lang3.ObjectUtils
|
||||
import org.mariotaku.chameleon.Chameleon
|
||||
import org.mariotaku.chameleon.ChameleonUtils
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.ktextension.Bundle
|
||||
import org.mariotaku.ktextension.empty
|
||||
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.Referral
|
||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
|
||||
import org.mariotaku.twidere.constant.profileImageStyleKey
|
||||
import org.mariotaku.twidere.fragment.AbsStatusesFragment.StatusesFragmentDelegate
|
||||
import org.mariotaku.twidere.fragment.UserTimelineFragment.UserTimelineFragmentDelegate
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback
|
||||
@ -706,11 +708,13 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||
ViewCompat.setElevation(toolbarTabs, actionBarElevation)
|
||||
|
||||
setupBaseActionBar()
|
||||
setupViewStyle()
|
||||
setupUserPages()
|
||||
|
||||
getUserInfo(accountId, userId, screenName, false)
|
||||
}
|
||||
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
bus.register(this)
|
||||
@ -1332,6 +1336,11 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||
actionBar.setBackgroundDrawable(actionBarBackground)
|
||||
}
|
||||
|
||||
|
||||
private fun setupViewStyle() {
|
||||
profileImage.style = preferences[profileImageStyleKey]
|
||||
}
|
||||
|
||||
private fun setupUserPages() {
|
||||
val args = arguments
|
||||
val tabArgs = Bundle()
|
||||
|
@ -24,7 +24,6 @@ import android.support.v4.view.MarginLayoutParamsCompat
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import org.mariotaku.twidere.R
|
||||
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.view.BadgeView
|
||||
import org.mariotaku.twidere.view.IconActionView
|
||||
import org.mariotaku.twidere.view.ProfileImageView
|
||||
import org.mariotaku.twidere.view.ShortTimeView
|
||||
import org.mariotaku.twidere.view.iface.IColorLabelView
|
||||
|
||||
/**
|
||||
* 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 activityTypeView: IconActionView
|
||||
@ -50,7 +53,7 @@ class ActivityTitleSummaryViewHolder(private val adapter: ParcelableActivitiesAd
|
||||
private val timeView: ShortTimeView
|
||||
private val profileImagesContainer: ViewGroup
|
||||
private val profileImageMoreNumber: BadgeView
|
||||
private val profileImageViews: Array<ImageView>
|
||||
private val profileImageViews: Array<ProfileImageView>
|
||||
private val profileImageSpace: View
|
||||
|
||||
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
|
||||
profileImageViews = arrayOf(
|
||||
itemView.findViewById(R.id.activity_profile_image_0) as ImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_1) as ImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_2) as ImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_3) as ImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_4) as ImageView
|
||||
itemView.findViewById(R.id.activity_profile_image_0) as ProfileImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_1) as ProfileImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_2) as ProfileImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_3) as ProfileImageView,
|
||||
itemView.findViewById(R.id.activity_profile_image_4) as ProfileImageView
|
||||
)
|
||||
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
|
||||
summaryView.textSize = textSize * 0.85f
|
||||
timeView.textSize = textSize * 0.80f
|
||||
|
||||
profileImageViews.forEach {
|
||||
it.style = adapter.profileImageStyle
|
||||
}
|
||||
}
|
||||
|
||||
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.HtmlEscapeHelper.toPlainText
|
||||
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
|
||||
import org.mariotaku.twidere.view.ProfileImageView
|
||||
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
||||
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 {
|
||||
|
||||
override val profileImageView: ImageView by lazy { itemView.profileImage }
|
||||
override val profileImageView: ProfileImageView by lazy { itemView.profileImage }
|
||||
override val profileTypeView: ImageView by lazy { itemView.profileType }
|
||||
|
||||
private val itemContent by lazy { itemView.itemContent }
|
||||
@ -460,6 +461,8 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
|
||||
|
||||
fun setupViewOptions() {
|
||||
setTextSize(adapter.textSize)
|
||||
profileImageView.style = adapter.profileImageStyle
|
||||
|
||||
mediaPreview.setStyle(adapter.mediaPreviewStyle)
|
||||
quotedMediaPreview.setStyle(adapter.mediaPreviewStyle)
|
||||
// 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.getUserTypeIconRes
|
||||
import org.mariotaku.twidere.view.NameView
|
||||
import org.mariotaku.twidere.view.ProfileImageView
|
||||
import org.mariotaku.twidere.view.iface.IColorLabelView
|
||||
import java.util.*
|
||||
|
||||
@ -44,7 +45,7 @@ class UserViewHolder(
|
||||
) : ViewHolder(itemView), OnClickListener, OnLongClickListener {
|
||||
|
||||
private val itemContent: IColorLabelView
|
||||
val profileImageView: ImageView
|
||||
val profileImageView: ProfileImageView
|
||||
val profileTypeView: ImageView
|
||||
private val nameView: NameView
|
||||
private val externalIndicator: TextView
|
||||
@ -270,6 +271,7 @@ class UserViewHolder(
|
||||
}
|
||||
|
||||
fun setupViewOptions() {
|
||||
profileImageView.style = adapter.profileImageStyle
|
||||
setTextSize(adapter.textSize)
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,8 @@
|
||||
~ 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_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
@ -31,7 +32,7 @@
|
||||
android:layout_width="@dimen/icon_size_list_item_small"
|
||||
android:layout_height="@dimen/icon_size_list_item_small"
|
||||
android:contentDescription="@string/icon"
|
||||
android:scaleType="fitCenter" />
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -47,15 +48,15 @@
|
||||
android:id="@android:id/text1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:maxLines="1"/>
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/text2"
|
||||
android:layout_width="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>
|
@ -33,7 +33,7 @@
|
||||
app:ignorePadding="true"
|
||||
tools:context=".adapter.MessageEntriesAdapter">
|
||||
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
<org.mariotaku.twidere.view.ProfileImageView
|
||||
android:id="@+id/profileImage"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/icon_size_card_list_item"
|
||||
@ -86,9 +86,9 @@
|
||||
android:layout_alignParentRight="true"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
tools:text="12:00"
|
||||
android:maxLines="1"/>
|
||||
tools:text="12:00"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
@ -98,9 +98,9 @@
|
||||
android:layout_alignStart="@+id/name"
|
||||
android:layout_below="@+id/name"
|
||||
android:layout_marginTop="@dimen/element_spacing_xsmall"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
tools:text="@string/sample_status_text"
|
||||
android:maxLines="1"/>
|
||||
tools:text="@string/sample_status_text"/>
|
||||
</RelativeLayout>
|
||||
|
||||
</org.mariotaku.twidere.view.ColorLabelRelativeLayout>
|
Loading…
x
Reference in New Issue
Block a user