migrating to kotlin

This commit is contained in:
Mariotaku Lee 2016-07-07 11:42:08 +08:00
parent 0515fd6cf9
commit 4d7a56b1a2
51 changed files with 1320 additions and 1657 deletions

View File

@ -213,7 +213,7 @@ public class AccountSelectorActivity extends BaseActivity implements
protected void onResume() {
super.onResume();
final boolean displayProfileImage = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
mAdapter.setDisplayProfileImage(displayProfileImage);
mAdapter.setProfileImageDisplayed(displayProfileImage);
}
@Override

View File

@ -1,90 +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.activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.Toolbar;
import com.soundcloud.android.crop.CropImageActivity;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.iface.IThemedActivity;
import org.mariotaku.twidere.util.ThemeUtils;
/**
* Created by mariotaku on 15/6/16.
*/
public class ImageCropperActivity extends CropImageActivity implements IThemedActivity {
// Data fields
private int mCurrentThemeColor;
private int mCurrentThemeBackgroundAlpha;
private String mCurrentThemeBackgroundOption;
private Toolbar mDoneCancelBar;
@Override
public void onContentChanged() {
super.onContentChanged();
mDoneCancelBar = (Toolbar) findViewById(R.id.done_cancel_bar);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void setContentView(final int layoutResID) {
super.setContentView(R.layout.activity_image_cropper);
}
@Override
public int getCurrentThemeBackgroundAlpha() {
return mCurrentThemeBackgroundAlpha;
}
@Override
public String getCurrentThemeBackgroundOption() {
return mCurrentThemeBackgroundOption;
}
@Override
public int getThemeBackgroundAlpha() {
return ThemeUtils.getUserThemeBackgroundAlpha(this);
}
@Override
public String getThemeBackgroundOption() {
return ThemeUtils.getThemeBackgroundOption(this);
}
@Override
protected void onApplyThemeResource(@NonNull Resources.Theme theme, int resId, boolean first) {
mCurrentThemeBackgroundAlpha = getThemeBackgroundAlpha();
mCurrentThemeBackgroundOption = getThemeBackgroundOption();
super.onApplyThemeResource(theme, resId, first);
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.activity
import android.os.Bundle
import android.support.v7.widget.Toolbar
import com.soundcloud.android.crop.CropImageActivity
import org.mariotaku.twidere.R
import org.mariotaku.twidere.activity.iface.IThemedActivity
import org.mariotaku.twidere.util.ThemeUtils
/**
* Created by mariotaku on 15/6/16.
*/
class ImageCropperActivity : CropImageActivity(), IThemedActivity {
// Data fields
override val currentThemeBackgroundAlpha by lazy { themeBackgroundAlpha }
override val currentThemeBackgroundOption by lazy { themeBackgroundOption }
private var mDoneCancelBar: Toolbar? = null
override fun onContentChanged() {
super.onContentChanged()
mDoneCancelBar = findViewById(R.id.done_cancel_bar) as Toolbar
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun setContentView(layoutResID: Int) {
super.setContentView(R.layout.activity_image_cropper)
}
override val themeBackgroundAlpha: Int
get() = ThemeUtils.getUserThemeBackgroundAlpha(this)
override val themeBackgroundOption: String
get() = ThemeUtils.getThemeBackgroundOption(this)
}

View File

@ -1,199 +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.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import com.mobeta.android.dslv.SimpleDragSortCursorAdapter;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableAccountCursorIndices;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.view.holder.AccountViewHolder;
import javax.inject.Inject;
public class AccountsAdapter extends SimpleDragSortCursorAdapter implements IBaseAdapter {
@Inject
MediaLoaderWrapper mImageLoader;
private boolean mDisplayProfileImage;
private boolean mSortEnabled;
private ParcelableAccountCursorIndices mIndices;
private boolean mSwitchEnabled;
private OnAccountToggleListener mOnAccountToggleListener;
private CompoundButton.OnCheckedChangeListener mCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final Object tag = buttonView.getTag();
if (!(tag instanceof String) || mOnAccountToggleListener == null) return;
final UserKey accountKey = UserKey.valueOf((String) tag);
mOnAccountToggleListener.onAccountToggle(accountKey, isChecked);
}
};
public AccountsAdapter(final Context context) {
super(context, R.layout.list_item_account, null, new String[]{Accounts.NAME},
new int[]{android.R.id.text1}, 0);
GeneralComponentHelper.build(context).inject(this);
}
public ParcelableAccount getAccount(int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
return mIndices.newObject(c);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
final int color = cursor.getInt(mIndices.color);
final AccountViewHolder holder = (AccountViewHolder) view.getTag();
holder.screenName.setText(String.format("@%s", cursor.getString(mIndices.screen_name)));
holder.setAccountColor(color);
if (mDisplayProfileImage) {
final ParcelableUser user = JsonSerializer.parse(cursor.getString(mIndices.account_user),
ParcelableUser.class);
if (user != null) {
mImageLoader.displayProfileImage(holder.profileImage, user);
} else {
mImageLoader.displayProfileImage(holder.profileImage,
cursor.getString(mIndices.profile_image_url));
}
} else {
mImageLoader.cancelDisplayTask(holder.profileImage);
}
final String accountType = cursor.getString(mIndices.account_type);
holder.accountType.setImageResource(ParcelableAccountUtils.getAccountTypeIcon(accountType));
holder.toggle.setChecked(cursor.getShort(mIndices.is_activated) == 1);
holder.toggle.setOnCheckedChangeListener(mCheckedChangeListener);
holder.toggle.setTag(cursor.getString(mIndices.account_key));
holder.toggleContainer.setVisibility(mSwitchEnabled ? View.VISIBLE : View.GONE);
holder.setSortEnabled(mSortEnabled);
super.bindView(view, context, cursor);
}
@Override
public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
final View view = super.newView(context, cursor, parent);
final AccountViewHolder holder = new AccountViewHolder(view);
view.setTag(holder);
return view;
}
@Override
public MediaLoaderWrapper getImageLoader() {
return mImageLoader;
}
@Override
public int getLinkHighlightOption() {
return 0;
}
@Override
public void setLinkHighlightOption(String option) {
}
@Override
public float getTextSize() {
return 0;
}
@Override
public void setTextSize(float textSize) {
}
@Override
public boolean isDisplayNameFirst() {
return false;
}
@Override
public void setDisplayNameFirst(boolean nameFirst) {
}
@Override
public boolean isProfileImageDisplayed() {
return mDisplayProfileImage;
}
@Override
public boolean isShowAccountColor() {
return false;
}
@Override
public void setShowAccountColor(boolean show) {
}
public void setSwitchEnabled(final boolean enabled) {
if (mSwitchEnabled == enabled) return;
mSwitchEnabled = enabled;
notifyDataSetChanged();
}
@Override
public void setDisplayProfileImage(final boolean display) {
mDisplayProfileImage = display;
notifyDataSetChanged();
}
public void setOnAccountToggleListener(OnAccountToggleListener listener) {
mOnAccountToggleListener = listener;
}
@Override
@Nullable
public Cursor swapCursor(@Nullable final Cursor cursor) {
if (cursor != null) {
mIndices = new ParcelableAccountCursorIndices(cursor);
}
return super.swapCursor(cursor);
}
public void setSortEnabled(boolean sortEnabled) {
if (mSortEnabled == sortEnabled) return;
mSortEnabled = sortEnabled;
notifyDataSetChanged();
}
public interface OnAccountToggleListener {
void onAccountToggle(UserKey accountId, boolean state);
}
}

View File

@ -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.adapter;
import android.content.Context;
import android.support.annotation.NonNull;
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.TwidereConstants;
import org.mariotaku.twidere.constant.SharedPreferenceConstants;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.util.Collection;
import javax.inject.Inject;
public class AccountsSpinnerAdapter extends ArrayAdapter<ParcelableCredentials> {
@Inject
MediaLoaderWrapper mImageLoader;
private final boolean mDisplayProfileImage;
private final Context mContext;
private String mDummyItemText;
public AccountsSpinnerAdapter(final Context context) {
this(context, R.layout.list_item_user);
}
public AccountsSpinnerAdapter(final Context context, int itemViewResource) {
super(context, itemViewResource);
GeneralComponentHelper.build(context).inject(this);
mContext = context;
mDisplayProfileImage = context.getSharedPreferences(TwidereConstants.SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE).getBoolean(SharedPreferenceConstants.KEY_DISPLAY_PROFILE_IMAGE, true);
}
public AccountsSpinnerAdapter(final Context context, final Collection<ParcelableCredentials> accounts) {
this(context);
addAll(accounts);
}
@Override
public long getItemId(int position) {
return getItem(position).hashCode();
}
@Override
public View getDropDownView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getDropDownView(position, convertView, parent);
bindView(view, getItem(position));
return view;
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
bindView(view, getItem(position));
return view;
}
private void bindView(final View view, final ParcelableCredentials item) {
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);
if (!item.is_dummy) {
if (text1 != null) {
text1.setVisibility(View.VISIBLE);
text1.setText(item.name);
}
if (text2 != null) {
text2.setVisibility(View.VISIBLE);
text2.setText(String.format("@%s", item.screen_name));
}
if (icon != null) {
icon.setVisibility(View.VISIBLE);
if (mDisplayProfileImage) {
mImageLoader.displayProfileImage(icon, item);
} else {
mImageLoader.cancelDisplayTask(icon);
// icon.setImageResource(R.drawable.ic_profile_image_default);
}
}
} else {
if (text1 != null) {
text1.setVisibility(View.VISIBLE);
text1.setText(mDummyItemText);
}
if (text2 != null) {
text2.setVisibility(View.GONE);
}
if (icon != null) {
icon.setVisibility(View.GONE);
}
}
}
public void setDummyItemText(int textRes) {
setDummyItemText(mContext.getString(textRes));
}
public void setDummyItemText(String text) {
mDummyItemText = text;
notifyDataSetChanged();
}
public int findPositionByKey(@NonNull UserKey key) {
for (int i = 0, j = getCount(); i < j; i++) {
if (key.equals(getItem(i).account_key)) {
return i;
}
}
return -1;
}
}

View File

@ -1,71 +0,0 @@
package org.mariotaku.twidere.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView.ViewHolder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Created by mariotaku on 14/10/27.
*/
public abstract class ArrayRecyclerAdapter<T, H extends ViewHolder> extends BaseRecyclerViewAdapter<H> {
protected final ArrayList<T> mData = new ArrayList<>();
public ArrayRecyclerAdapter(Context context) {
super(context);
}
@Override
public final void onBindViewHolder(H holder, int position) {
onBindViewHolder(holder, position, getItem(position));
}
public abstract void onBindViewHolder(H holder, int position, T item);
public void add(final T item) {
if (item == null) return;
mData.add(item);
notifyDataSetChanged();
}
public void addAll(final Collection<? extends T> collection) {
mData.addAll(collection);
notifyDataSetChanged();
}
public void clear() {
mData.clear();
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return mData.size();
}
public T getItem(final int position) {
return mData.get(position);
}
public boolean remove(final int position) {
mData.remove(position);
notifyItemRemoved(position);
return true;
}
public void removeAll(final List<T> collection) {
mData.removeAll(collection);
notifyDataSetChanged();
}
public void sort(final Comparator<? super T> comparator) {
Collections.sort(mData, comparator);
notifyDataSetChanged();
}
}

View File

@ -1,150 +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.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.MultiSelectManager;
import org.mariotaku.twidere.util.OnLinkClickHandler;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.TwidereLinkify;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.util.Collection;
import javax.inject.Inject;
public class BaseArrayAdapter<T> extends ArrayAdapter<T> implements Constants, IBaseAdapter,
OnSharedPreferenceChangeListener {
private final TwidereLinkify mLinkify;
@Inject
protected UserColorNameManager mUserColorNameManager;
private float mTextSize;
private int mLinkHighlightOption;
private boolean mDisplayProfileImage, mDisplayNameFirst, mShowAccountColor;
private final SharedPreferences mNicknamePrefs, mColorPrefs;
@Inject
protected MediaLoaderWrapper mImageLoader;
@Inject
protected MultiSelectManager mMultiSelectManager;
@Inject
protected SharedPreferencesWrapper mPreferences;
public BaseArrayAdapter(final Context context, final int layoutRes) {
this(context, layoutRes, null);
}
public BaseArrayAdapter(final Context context, final int layoutRes, final Collection<? extends T> collection) {
super(context, layoutRes, collection);
//noinspection unchecked
GeneralComponentHelper.build(context).inject((BaseArrayAdapter<Object>) this);
final TwidereApplication app = TwidereApplication.Companion.getInstance(context);
mLinkify = new TwidereLinkify(new OnLinkClickHandler(context, mMultiSelectManager, mPreferences));
mNicknamePrefs = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE);
mColorPrefs = context.getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE);
mNicknamePrefs.registerOnSharedPreferenceChangeListener(this);
mColorPrefs.registerOnSharedPreferenceChangeListener(this);
}
@NonNull
@Override
public MediaLoaderWrapper getImageLoader() {
return mImageLoader;
}
@Override
public final int getLinkHighlightOption() {
return mLinkHighlightOption;
}
public final TwidereLinkify getLinkify() {
return mLinkify;
}
@Override
public final float getTextSize() {
return mTextSize;
}
@Override
public final boolean isDisplayNameFirst() {
return mDisplayNameFirst;
}
@Override
public final boolean isProfileImageDisplayed() {
return mDisplayProfileImage;
}
@Override
public final boolean isShowAccountColor() {
return mShowAccountColor;
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
if (KEY_DISPLAY_PROFILE_IMAGE.equals(key) || KEY_MEDIA_PREVIEW_STYLE.equals(key)
|| KEY_DISPLAY_SENSITIVE_CONTENTS.equals(key)) {
notifyDataSetChanged();
}
}
@Override
public final void setDisplayNameFirst(final boolean nameFirst) {
mDisplayNameFirst = nameFirst;
}
@Override
public final void setDisplayProfileImage(final boolean display) {
mDisplayProfileImage = display;
}
@Override
public final void setLinkHighlightOption(@NonNull final String option) {
final int optionInt = Utils.getLinkHighlightingStyleInt(option);
mLinkify.setHighlightOption(optionInt);
if (optionInt == mLinkHighlightOption) return;
mLinkHighlightOption = optionInt;
}
@Override
public final void setShowAccountColor(final boolean show) {
mShowAccountColor = show;
}
@Override
public final void setTextSize(final float textSize) {
mTextSize = textSize;
}
}

View File

@ -1,82 +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.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.loader.ExtensionsListLoader.ExtensionInfo;
import org.mariotaku.twidere.util.PermissionsManager;
import org.mariotaku.twidere.view.holder.CheckableTwoLineWithIconViewHolder;
import java.util.List;
public class ExtensionsAdapter extends ArrayAdapter<ExtensionInfo> {
private final PermissionsManager mPermissionsManager;
public ExtensionsAdapter(final Context context) {
super(context, R.layout.list_item_two_line_checked);
mPermissionsManager = new PermissionsManager(context);
}
@Override
public long getItemId(final int position) {
return getItem(position).hashCode();
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
final CheckableTwoLineWithIconViewHolder holder;
final Object tag = view.getTag();
if (tag instanceof CheckableTwoLineWithIconViewHolder) {
holder = (CheckableTwoLineWithIconViewHolder) tag;
} else {
holder = new CheckableTwoLineWithIconViewHolder(view);
view.setTag(holder);
}
final ExtensionInfo info = getItem(position);
final boolean permissionValid = PermissionsManager.isPermissionValid(info.permissions);
holder.checkbox.setVisibility(permissionValid ? View.VISIBLE : View.GONE);
if (permissionValid) {
holder.checkbox.setChecked(mPermissionsManager.checkPermission(info.pname, info.permissions));
}
holder.text1.setText(info.label);
holder.text2.setVisibility(TextUtils.isEmpty(info.description) ? View.GONE : View.VISIBLE);
holder.text2.setText(info.description);
holder.icon.setImageDrawable(info.icon);
return view;
}
public void setData(final List<ExtensionInfo> data) {
clear();
if (data != null) {
addAll(data);
}
notifyDataSetChanged();
}
}

View File

@ -1,59 +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.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.model.ListAction;
public class ListActionAdapter extends ArrayAdapter<ListAction> {
public ListActionAdapter(final Context context) {
super(context, R.layout.list_action_item, android.R.id.text1);
}
public ListAction findItem(final long id) {
for (int i = 0, count = getCount(); i < count; i++) {
if (id == getItemId(i)) return getItem(i);
}
return null;
}
@Override
public long getItemId(final int position) {
return getItem(position).getOrder();
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
final TextView summary_view = (TextView) view.findViewById(android.R.id.text2);
final String summary = getItem(position).getSummary();
summary_view.setText(summary);
summary_view.setVisibility(!TextUtils.isEmpty(summary) ? View.VISIBLE : View.GONE);
return view;
}
}

View File

@ -1,96 +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.view.View;
import android.view.ViewGroup;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.configBaseAdapter;
public class SimpleParcelableUserListsAdapter extends BaseArrayAdapter<ParcelableUserList> implements IBaseAdapter {
private final Context mContext;
public SimpleParcelableUserListsAdapter(final Context context) {
super(context, R.layout.list_item_two_line);
mContext = context;
configBaseAdapter(context, this);
}
public void appendData(final List<ParcelableUserList> data) {
setData(data, false);
}
@Override
public long getItemId(final int position) {
return getItem(position) != null ? getItem(position).hashCode() : -1;
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
final Object tag = view.getTag();
final TwoLineWithIconViewHolder holder;
if (tag instanceof TwoLineWithIconViewHolder) {
holder = (TwoLineWithIconViewHolder) tag;
} else {
holder = new TwoLineWithIconViewHolder(view);
view.setTag(holder);
}
// Clear images in order to prevent images in recycled view shown.
holder.icon.setImageDrawable(null);
final ParcelableUserList user_list = getItem(position);
final String display_name = mUserColorNameManager.getDisplayName(user_list, isDisplayNameFirst()
);
holder.text1.setText(user_list.name);
holder.text2.setText(mContext.getString(R.string.created_by, display_name));
holder.icon.setVisibility(isProfileImageDisplayed() ? View.VISIBLE : View.GONE);
if (isProfileImageDisplayed()) {
mImageLoader.displayProfileImage(holder.icon, user_list.user_profile_image_url);
} else {
mImageLoader.cancelDisplayTask(holder.icon);
}
return view;
}
public void setData(final List<ParcelableUserList> data, final boolean clearOld) {
if (clearOld) {
clear();
}
if (data == null) return;
for (final ParcelableUserList user : data) {
//TODO improve compare
if (clearOld || findItemPosition(user.hashCode()) < 0) {
add(user);
}
}
}
}

View File

@ -1,109 +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.support.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.configBaseAdapter;
import static org.mariotaku.twidere.util.Utils.getUserTypeIconRes;
public class SimpleParcelableUsersAdapter extends BaseArrayAdapter<ParcelableUser> implements IBaseAdapter {
public SimpleParcelableUsersAdapter(final Context context) {
this(context, R.layout.list_item_user);
}
public SimpleParcelableUsersAdapter(final Context context, final int layoutRes) {
super(context, layoutRes);
configBaseAdapter(context, this);
}
@Override
public long getItemId(final int position) {
final ParcelableUser item = getItem(position);
if (item != null) {
return item.hashCode();
} else {
return -1;
}
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
final Object tag = view.getTag();
final TwoLineWithIconViewHolder holder;
if (tag instanceof TwoLineWithIconViewHolder) {
holder = (TwoLineWithIconViewHolder) tag;
} else {
holder = new TwoLineWithIconViewHolder(view);
view.setTag(holder);
}
final ParcelableUser user = getItem(position);
holder.text1.setCompoundDrawablesWithIntrinsicBounds(0, 0,
getUserTypeIconRes(user.is_verified, user.is_protected), 0);
holder.text1.setText(mUserColorNameManager.getUserNickname(user.key, user.name));
holder.text2.setText(String.format("@%s", user.screen_name));
holder.icon.setVisibility(isProfileImageDisplayed() ? View.VISIBLE : View.GONE);
if (isProfileImageDisplayed()) {
mImageLoader.displayProfileImage(holder.icon, user);
} else {
mImageLoader.cancelDisplayTask(holder.icon);
}
return view;
}
public void setData(final List<ParcelableUser> data) {
setData(data, false);
}
public void setData(final List<ParcelableUser> data, final boolean clearOld) {
if (clearOld) {
clear();
}
if (data == null) return;
for (final ParcelableUser user : data) {
if (clearOld || findUserPosition(user.key) < 0) {
add(user);
}
}
}
public int findUserPosition(@NonNull UserKey userKey) {
for (int i = 0, j = getCount(); i < j; i++) {
if (userKey.equals(getItem(i).key)) return i;
}
return -1;
}
}

View File

@ -1,88 +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.database.sqlite.SQLiteDatabase;
import android.support.annotation.Nullable;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
import android.widget.TextView;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedStatuses;
import org.mariotaku.twidere.util.HtmlEscapeHelper;
public class SourceAutoCompleteAdapter extends SimpleCursorAdapter {
private static final String[] COLUMNS = new String[]{CachedStatuses._ID, CachedStatuses.SOURCE};
private static final String[] FROM = new String[0];
private static final int[] TO = new int[0];
private final SQLiteDatabase mDatabase;
private int mSourceIdx;
public SourceAutoCompleteAdapter(final Context context) {
super(context, android.R.layout.simple_list_item_1, null, FROM, TO, 0);
final TwidereApplication app = TwidereApplication.Companion.getInstance(context);
mDatabase = app.getSqLiteDatabase();
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
if (isCursorClosed()) return;
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
text1.setText(convertToString(cursor));
super.bindView(view, context, cursor);
}
@Override
public CharSequence convertToString(final Cursor cursor) {
if (isCursorClosed() || mSourceIdx == -1) return null;
return HtmlEscapeHelper.toPlainText(cursor.getString(mSourceIdx));
}
public boolean isCursorClosed() {
final Cursor cursor = getCursor();
return cursor == null || cursor.isClosed();
}
@Override
public Cursor runQueryOnBackgroundThread(final CharSequence constraint) {
final String constraint_escaped = constraint != null ? constraint.toString().replaceAll("_", "^_") : null;
final String selection = constraint != null ? CachedStatuses.SOURCE + " LIKE '%\">'||?||'%</a>' ESCAPE '^'"
: null;
final String[] selectionArgs = constraint != null ? new String[]{constraint_escaped} : null;
return mDatabase.query(true, CachedStatuses.TABLE_NAME, COLUMNS, selection, selectionArgs,
CachedStatuses.SOURCE, null, null, null);
}
@Override
@Nullable
public Cursor swapCursor(@Nullable final Cursor cursor) {
if (cursor != null) {
mSourceIdx = cursor.getColumnIndex(CachedStatuses.SOURCE);
}
return super.swapCursor(cursor);
}
}

View File

@ -1,195 +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.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.View;
import android.view.ViewGroup;
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
import org.mariotaku.twidere.model.SupportTabSpec;
import org.mariotaku.twidere.view.iface.PagerIndicator;
import org.mariotaku.twidere.view.iface.PagerIndicator.TabListener;
import org.mariotaku.twidere.view.iface.PagerIndicator.TabProvider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.mariotaku.twidere.util.CustomTabUtils.getTabIconDrawable;
import static org.mariotaku.twidere.util.Utils.announceForAccessibilityCompat;
public class SupportTabsAdapter extends SupportFixedFragmentStatePagerAdapter implements TabProvider, TabListener {
private static final String EXTRA_ADAPTER_POSITION = "adapter_position";
private final ArrayList<SupportTabSpec> mTabs = new ArrayList<>();
private final Context mContext;
private final PagerIndicator mIndicator;
private final int mColumns;
public SupportTabsAdapter(final Context context, final FragmentManager fm) {
this(context, fm, null);
}
public SupportTabsAdapter(final Context context, final FragmentManager fm, final PagerIndicator indicator) {
this(context, fm, indicator, 1);
}
public SupportTabsAdapter(final Context context, final FragmentManager fm, final PagerIndicator indicator,
final int columns) {
super(fm);
mContext = context;
mIndicator = indicator;
mColumns = columns;
clear();
}
public void addTab(final Class<? extends Fragment> cls, final Bundle args, final String name,
final Integer icon, final int position, final String tag) {
addTab(new SupportTabSpec(name, icon, cls, args, position, tag));
}
public void addTab(final Class<? extends Fragment> cls, final Bundle args, final String name,
final Integer icon, final String type, final int position, final String tag) {
addTab(new SupportTabSpec(name, icon, type, cls, args, position, tag));
}
public void addTab(final SupportTabSpec spec) {
mTabs.add(spec);
notifyDataSetChanged();
}
public void addTabs(final Collection<? extends SupportTabSpec> specs) {
mTabs.addAll(specs);
notifyDataSetChanged();
}
public void clear() {
mTabs.clear();
notifyDataSetChanged();
}
@Override
public int getCount() {
return mTabs.size();
}
@Override
public int getItemPosition(Object object) {
if (!(object instanceof Fragment)) return POSITION_NONE;
final Bundle args = ((Fragment) object).getArguments();
if (args == null) return POSITION_NONE;
return args.getInt(EXTRA_ADAPTER_POSITION, POSITION_NONE);
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
if (mIndicator != null) {
mIndicator.notifyDataSetChanged();
}
}
@Override
public CharSequence getPageTitle(final int position) {
return mTabs.get(position).name;
}
@Override
public float getPageWidth(final int position) {
return 1.0f / mColumns;
}
@Override
public Fragment getItem(final int position) {
final Fragment fragment = Fragment.instantiate(mContext, mTabs.get(position).cls.getName());
fragment.setArguments(getPageArguments(mTabs.get(position).args, position));
return fragment;
}
@Override
public void startUpdate(ViewGroup container) {
super.startUpdate(container);
}
@Override
public Drawable getPageIcon(final int position) {
return getTabIconDrawable(mContext, mTabs.get(position).icon);
}
@NonNull
public SupportTabSpec getTab(final int position) {
return mTabs.get(position);
}
public List<SupportTabSpec> getTabs() {
return mTabs;
}
@Override
public void onPageReselected(final int position) {
if (!(mContext instanceof SupportFragmentCallback)) return;
final Fragment f = ((SupportFragmentCallback) mContext).getCurrentVisibleFragment();
if (f instanceof RefreshScrollTopInterface) {
((RefreshScrollTopInterface) f).scrollToStart();
}
}
@Override
public void onPageSelected(final int position) {
if (mIndicator == null || position < 0 || position >= getCount()) return;
announceForAccessibilityCompat(mContext, (View) mIndicator, getPageTitle(position), getClass());
}
@Override
public boolean onTabLongClick(final int position) {
if (!(mContext instanceof SupportFragmentCallback)) return false;
if (((SupportFragmentCallback) mContext).triggerRefresh(position)) return true;
final Fragment f = ((SupportFragmentCallback) mContext).getCurrentVisibleFragment();
if (f instanceof RefreshScrollTopInterface)
return ((RefreshScrollTopInterface) f).triggerRefresh();
return false;
}
public void setTabLabel(int position, CharSequence label) {
for (SupportTabSpec spec : mTabs) {
if (position == spec.position)
spec.name = label;
}
notifyDataSetChanged();
}
private Bundle getPageArguments(Bundle args, int position) {
if (args == null) {
args = new Bundle();
}
args.putInt(EXTRA_ADAPTER_POSITION, position);
return args;
}
}

View File

@ -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.adapter;
import android.content.Context;
import android.database.Cursor;
import android.support.annotation.Nullable;
import android.support.v4.widget.SimpleCursorAdapter;
import org.mariotaku.twidere.provider.TwidereDataStore;
/**
* Created by mariotaku on 15/4/29.
*/
public class TrendsAdapter extends SimpleCursorAdapter {
private int mNameIdx;
@Override
public String getItem(int position) {
final Cursor c = getCursor();
if (c != null && !c.isClosed() && c.moveToPosition(position))
return c.getString(mNameIdx);
return null;
}
@Override
@Nullable
public Cursor swapCursor(@Nullable Cursor c) {
if (c != null) {
mNameIdx = c.getColumnIndex(TwidereDataStore.CachedTrends.NAME);
}
return super.swapCursor(c);
}
public TrendsAdapter(final Context context) {
super(context, android.R.layout.simple_list_item_1, null, new String[]{TwidereDataStore.CachedTrends.NAME},
new int[]{android.R.id.text1}, 0);
}
}

View File

@ -1,151 +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.adapter;
import android.content.Context;
import android.database.Cursor;
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.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.model.UserKey;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
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 javax.inject.Inject;
import static org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_DISPLAY_PROFILE_IMAGE;
public class UserAutoCompleteAdapter extends SimpleCursorAdapter {
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 mIdIdx, mNameIdx, mScreenNameIdx, mProfileImageIdx;
private UserKey mAccountKey;
public UserAutoCompleteAdapter(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);
text1.setText(mUserColorNameManager.getUserNickname(cursor.getString(mIdIdx), cursor.getString(mNameIdx)));
text2.setText(String.format("@%s", cursor.getString(mScreenNameIdx)));
if (mDisplayProfileImage) {
final String profileImageUrl = cursor.getString(mProfileImageIdx);
mProfileImageLoader.displayProfileImage(icon, profileImageUrl);
} else {
mProfileImageLoader.cancelDisplayTask(icon);
}
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) {
return cursor.getString(mScreenNameIdx);
}
@Override
public Cursor runQueryOnBackgroundThread(final CharSequence constraint) {
if (TextUtils.isEmpty(constraint)) return null;
final FilterQueryProvider filter = getFilterQueryProvider();
if (filter != null) return filter.runQuery(constraint);
final String query = constraint.toString();
final String queryEscaped = query.replace("_", "^_");
final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
final Expression usersSelection = Expression.or(
Expression.likeRaw(new Columns.Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Columns.Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.inArgs(new Columns.Column(CachedUsers.USER_KEY), nicknameKeys.length));
//TODO
final String[] selectionArgs = new String[nicknameKeys.length + 2];
selectionArgs[0] = selectionArgs[1] = queryEscaped;
System.arraycopy(nicknameKeys, 0, selectionArgs, 2, nicknameKeys.length);
final String[] order = {CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME,
CachedUsers.NAME};
final boolean[] ascending = {false, false, true, true};
final OrderBy orderBy = new OrderBy(order, ascending);
final Uri uri = Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, String.valueOf(mAccountKey));
return mContext.getContentResolver().query(uri, CachedUsers.COLUMNS, usersSelection.getSQL(),
selectionArgs, orderBy.getSQL());
}
public void setAccountKey(UserKey accountKey) {
mAccountKey = accountKey;
}
@Override
@Nullable
public Cursor swapCursor(@Nullable final 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);
}
return super.swapCursor(cursor);
}
}

View File

@ -1,92 +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.model;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.annotation.CustomTabType;
import static org.mariotaku.twidere.util.CompareUtils.bundleEquals;
import static org.mariotaku.twidere.util.CompareUtils.objectEquals;
public class SupportTabSpec implements Comparable<SupportTabSpec>, TwidereConstants {
public CharSequence name;
public final Object icon;
@CustomTabType
@Nullable
public final String type;
public final Class<? extends Fragment> cls;
@Nullable
public final Bundle args;
public final int position;
public final String tag;
public SupportTabSpec(final String name, final Object icon, final Class<? extends Fragment> cls, final Bundle args,
final int position, String tag) {
this(name, icon, null, cls, args, position, tag);
}
public SupportTabSpec(final String name, final Object icon, @CustomTabType @Nullable final String type,
final Class<? extends Fragment> cls, @Nullable final Bundle args, final int position,
final String tag) {
if (cls == null) throw new IllegalArgumentException("Fragment cannot be null!");
if (name == null && icon == null)
throw new IllegalArgumentException("You must specify a name or icon for this tab!");
this.name = name;
this.icon = icon;
this.type = type;
this.cls = cls;
this.args = args;
this.position = position;
this.tag = tag;
}
@Override
public int compareTo(@NonNull final SupportTabSpec another) {
return position - another.position;
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof SupportTabSpec)) return false;
final SupportTabSpec spec = (SupportTabSpec) o;
return objectEquals(name, spec.name) && objectEquals(icon, spec.icon) && cls == spec.cls
&& bundleEquals(args, spec.args) && position == spec.position;
}
@Override
public String toString() {
return "SupportTabSpec{" +
"name=" + name +
", icon=" + icon +
", type='" + type + '\'' +
", cls=" + cls +
", args=" + args +
", position=" + position +
", tag='" + tag + '\'' +
'}';
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.model
import android.os.Bundle
import android.support.v4.app.Fragment
import org.mariotaku.twidere.annotation.CustomTabType
import org.mariotaku.twidere.util.CompareUtils.bundleEquals
import org.mariotaku.twidere.util.CompareUtils.objectEquals
data class SupportTabSpec(
var name: CharSequence? = null,
var icon: Any? = null,
@CustomTabType val type: String? = null,
var cls: Class<out Fragment>,
var args: Bundle? = null,
var position: Int,
var tag: String? = null
) : Comparable<SupportTabSpec> {
init {
if (name == null && icon == null)
throw IllegalArgumentException("You must specify a name or icon for this tab!")
}
override fun compareTo(other: SupportTabSpec): Int {
return position - other.position
}
override fun equals(other: Any?): Boolean {
if (other !is SupportTabSpec) return false
return objectEquals(name, other.name) && objectEquals(icon, other.icon) && cls == other.cls
&& bundleEquals(args, other.args) && position == other.position
}
override fun hashCode(): Int {
var result = name?.hashCode() ?: 0
result = 31 * result + (icon?.hashCode() ?: 0)
result = 31 * result + cls.hashCode()
result = 31 * result + (args?.hashCode() ?: 0)
result = 31 * result + position
return result
}
}

View File

@ -28,8 +28,11 @@ import org.mariotaku.twidere.constant.IntentConstants.EXTRA_URI
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_PHISHING_LINK_WARNING
import org.mariotaku.twidere.fragment.PhishingLinkWarningDialogFragment
class DirectMessageOnLinkClickHandler(context: Context, manager: MultiSelectManager,
preferences: SharedPreferencesWrapper) : OnLinkClickHandler(context, manager, preferences) {
class DirectMessageOnLinkClickHandler(
context: Context,
manager: MultiSelectManager?,
preferences: SharedPreferencesWrapper
) : OnLinkClickHandler(context, manager, preferences) {
override val isPrivateData: Boolean
get() = true

View File

@ -104,8 +104,9 @@ public class ThemeUtils implements Constants {
}
public static void applyWindowBackground(@NonNull Context context, @NonNull Window window, String option, int alpha) {
if (isWindowFloating(context)) return;
if (VALUE_THEME_BACKGROUND_TRANSPARENT.equals(option)) {
if (isWindowFloating(context)) {
window.setBackgroundDrawable(getWindowBackground(context));
} else if (VALUE_THEME_BACKGROUND_TRANSPARENT.equals(option)) {
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
window.setBackgroundDrawable(getWindowBackgroundFromThemeApplyAlpha(context, alpha));
} else if (VALUE_THEME_BACKGROUND_SOLID.equals(option)) {

View File

@ -419,7 +419,7 @@ public final class Utils implements Constants {
public static void configBaseAdapter(final Context context, final IBaseAdapter adapter) {
if (context == null) return;
final SharedPreferences pref = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
adapter.setDisplayProfileImage(pref.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true));
adapter.setProfileImageDisplayed(pref.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true));
adapter.setDisplayNameFirst(pref.getBoolean(KEY_NAME_FIRST, true));
adapter.setLinkHighlightOption(pref.getString(KEY_LINK_HIGHLIGHT_OPTION, VALUE_LINK_HIGHLIGHT_OPTION_NONE));
adapter.setTextSize(pref.getInt(KEY_TEXT_SIZE, getDefaultTextSize(context)));

View File

@ -24,7 +24,6 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Rect
import android.nfc.NfcAdapter
@ -47,6 +46,7 @@ import com.afollestad.appthemeengine.customizers.ATEToolbarCustomizer
import com.squareup.otto.Bus
import org.mariotaku.twidere.BuildConfig
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.TwidereConstants.SHARED_PREFERENCES_NAME
import org.mariotaku.twidere.activity.iface.IAppCompatActivity
import org.mariotaku.twidere.activity.iface.IControlBarActivity
import org.mariotaku.twidere.activity.iface.IExtendedActivity
@ -91,9 +91,6 @@ open class BaseActivity : ATEActivity(), Constants, IExtendedActivity, IThemedAc
private var mSystemWindowsInsets: Rect? = null
var keyMetaState: Int = 0
private set
// Data fields
private var mCurrentThemeBackgroundAlpha: Int = 0
private var mCurrentThemeBackgroundOption: String? = null
override fun getSystemWindowsInsets(insets: Rect): Boolean {
if (mSystemWindowsInsets == null) return false
@ -152,6 +149,7 @@ open class BaseActivity : ATEActivity(), Constants, IExtendedActivity, IThemedAc
StrictModeUtils.detectAllVmPolicy()
StrictModeUtils.detectAllThreadPolicy()
}
ThemeUtils.applyDayNight(getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE), delegate)
super.onCreate(savedInstanceState)
GeneralComponentHelper.build(this).inject(this)
}
@ -271,24 +269,17 @@ open class BaseActivity : ATEActivity(), Constants, IExtendedActivity, IThemedAc
}
override fun onApplyThemeResource(theme: Resources.Theme, resId: Int, first: Boolean) {
mCurrentThemeBackgroundAlpha = themeBackgroundAlpha
mCurrentThemeBackgroundOption = themeBackgroundOption
super.onApplyThemeResource(theme, resId, first)
val window = window
if (window != null && shouldApplyWindowBackground()) {
if (window != null && shouldApplyWindowBackground) {
ThemeUtils.applyWindowBackground(this, window, themeBackgroundOption,
themeBackgroundAlpha)
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
ThemeUtils.fixNightMode(resources, newConfig)
super.onConfigurationChanged(newConfig)
}
protected fun shouldApplyWindowBackground(): Boolean {
return true
}
protected val shouldApplyWindowBackground: Boolean
get() {
return true
}
override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? {
// Fix for https://github.com/afollestad/app-theme-engine/issues/109

View File

@ -106,17 +106,17 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
private var mLocationManager: LocationManager? = null
private var mTask: AsyncTask<Any, Any, *>? = null
private var mMenuInflater: SupportMenuInflater? = null
private var mItemTouchHelper: ItemTouchHelper? = null
private val supportMenuInflater by lazy { SupportMenuInflater(this) }
private var itemTouchHelper: ItemTouchHelper? = null
private val mBackTimeoutRunnable = Runnable { mNavigateBackPressed = false }
private val backTimeoutRunnable = Runnable { mNavigateBackPressed = false }
// Adapters
private var mMediaPreviewAdapter: MediaPreviewAdapter? = null
private var mediaPreviewAdapter: MediaPreviewAdapter? = null
private var accountsAdapter: AccountIconsAdapter? = null
// Data fields
private var mRecentLocation: ParcelableLocation? = null
private var recentLocation: ParcelableLocation? = null
private var mInReplyToStatus: ParcelableStatus? = null
private var mMentionUser: ParcelableUser? = null
private var mOriginalText: String? = null
@ -406,14 +406,11 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
override fun getMenuInflater(): MenuInflater {
if (mMenuInflater == null) {
mMenuInflater = SupportMenuInflater(this)
}
return mMenuInflater!!
return supportMenuInflater
}
fun removeAllMedia(list: List<ParcelableMediaUpdate>) {
mMediaPreviewAdapter!!.removeAll(list)
mediaPreviewAdapter!!.removeAll(list)
}
fun saveToDrafts() {
@ -428,7 +425,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
extra.setIsPossiblySensitive(possiblySensitive)
draft.action_extras = extra
draft.media = media
draft.location = mRecentLocation
draft.location = recentLocation
val values = DraftValuesCreator.create(draft)
val draftUri = contentResolver.insert(Drafts.CONTENT_URI, values)
displayNewDraftNotification(text, draftUri)
@ -536,14 +533,14 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
val adapter = MediaPreviewAdapter(this, PreviewGridOnStartDragListener(this))
mMediaPreviewAdapter = adapter
mItemTouchHelper = ItemTouchHelper(AttachedMediaItemTouchHelperCallback(adapter))
mediaPreviewAdapter = adapter
itemTouchHelper = ItemTouchHelper(AttachedMediaItemTouchHelperCallback(adapter))
val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
attachedMediaPreview.layoutManager = layoutManager
attachedMediaPreview.adapter = mMediaPreviewAdapter
attachedMediaPreview.adapter = mediaPreviewAdapter
registerForContextMenu(attachedMediaPreview)
mItemTouchHelper!!.attachToRecyclerView(attachedMediaPreview)
itemTouchHelper!!.attachToRecyclerView(attachedMediaPreview)
val previewGridSpacing = resources.getDimensionPixelSize(R.dimen.element_spacing_small)
attachedMediaPreview.addItemDecoration(PreviewGridItemDecoration(previewGridSpacing))
@ -590,7 +587,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
val menu = menuBar!!.menu
menuInflater.inflate(R.menu.menu_compose, menu)
supportMenuInflater.inflate(R.menu.menu_compose, menu)
ThemeUtils.wrapMenuIcon(menuBar)
send!!.setOnClickListener(this)
@ -627,7 +624,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo) {
if (v === attachedMediaPreview) {
menu.setHeaderTitle(R.string.edit_media)
menuInflater.inflate(R.menu.menu_attached_media_edit, menu)
supportMenuInflater.inflate(R.menu.menu_attached_media_edit, menu)
}
}
@ -637,7 +634,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
when (menuInfo.recyclerViewId) {
R.id.attachedMediaPreview -> {
val position = menuInfo.position
val mediaUpdate = mMediaPreviewAdapter!!.getItem(position)
val mediaUpdate = mediaPreviewAdapter!!.getItem(position)
val args = Bundle()
args.putString(EXTRA_TEXT, mediaUpdate.alt_text)
args.putInt(EXTRA_POSITION, position)
@ -705,8 +702,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
if (editText.length() == 0 && !textChanged) {
if (!mNavigateBackPressed) {
Toast.makeText(this, getString(R.string.press_again_to_close), Toast.LENGTH_SHORT).show()
editText.removeCallbacks(mBackTimeoutRunnable)
editText.postDelayed(mBackTimeoutRunnable, 2000)
editText.removeCallbacks(backTimeoutRunnable)
editText.postDelayed(backTimeoutRunnable, 2000)
} else {
onBackPressed()
}
@ -725,17 +722,17 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
private fun addMedia(media: ParcelableMediaUpdate) {
mMediaPreviewAdapter!!.add(media)
mediaPreviewAdapter!!.add(media)
updateAttachedMediaView()
}
private fun addMedia(media: List<ParcelableMediaUpdate>) {
mMediaPreviewAdapter!!.addAll(media)
mediaPreviewAdapter!!.addAll(media)
updateAttachedMediaView()
}
private fun clearMedia() {
mMediaPreviewAdapter!!.clear()
mediaPreviewAdapter!!.clear()
updateAttachedMediaView()
}
@ -768,7 +765,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
private val mediaList: List<ParcelableMediaUpdate>
get() = mMediaPreviewAdapter!!.asList
get() = mediaPreviewAdapter!!.asList
private fun handleDefaultIntent(intent: Intent?): Boolean {
if (intent == null) return false
@ -836,7 +833,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
if (draft.media != null) {
addMedia(Arrays.asList(*draft.media))
}
mRecentLocation = draft.location
recentLocation = draft.location
if (draft.action_extras is UpdateStatusActionExtra) {
val extra = draft.action_extras as UpdateStatusActionExtra?
possiblySensitive = extra!!.isPossiblySensitive
@ -1061,7 +1058,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
private fun hasMedia(): Boolean {
return mMediaPreviewAdapter!!.itemCount > 0
return mediaPreviewAdapter!!.itemCount > 0
}
private val isQuote: Boolean
@ -1172,7 +1169,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
if (attachPreciseLocation) {
locationText!!.text = ParcelableLocationUtils.getHumanReadableString(location, 3)
} else {
if (locationText!!.tag == null || location != mRecentLocation) {
if (locationText!!.tag == null || location != recentLocation) {
val task = DisplayPlaceNameTask(this)
task.params = location
task.setCallback(locationText)
@ -1182,7 +1179,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
} else {
locationText!!.setText(R.string.unknown_location)
}
mRecentLocation = location
recentLocation = location
}
/**
@ -1244,8 +1241,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
locationIcon!!.isActivated = attachLocation
if (!attachLocation) {
locationText!!.setText(R.string.no_location)
} else if (mRecentLocation != null) {
setRecentLocation(mRecentLocation)
} else if (recentLocation != null) {
setRecentLocation(recentLocation)
} else {
locationText!!.setText(R.string.getting_location)
}
@ -1283,7 +1280,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
update.accounts = ParcelableAccountUtils.getAccounts(this, *accountKeys)
update.text = text
if (attachLocation) {
update.location = mRecentLocation
update.location = recentLocation
update.display_coordinates = attachPreciseLocation
}
update.media = media
@ -1692,7 +1689,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
val asList: List<ParcelableMediaUpdate>
get() = Collections.unmodifiableList(mData)
get() = Collections.unmodifiableList(data)
override fun getItemId(position: Int): Long {
return getItem(position).hashCode().toLong()
@ -1731,13 +1728,13 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
Collections.swap(mData, fromPosition, toPosition)
Collections.swap(data, fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
return true
}
fun setAltText(position: Int, altText: String?) {
mData[position].alt_text = altText
data[position].alt_text = altText
notifyDataSetChanged()
}
}
@ -1806,7 +1803,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
private fun setMediaAltText(position: Int, altText: String?) {
mMediaPreviewAdapter!!.setAltText(position, altText)
mediaPreviewAdapter!!.setAltText(position, altText)
}
class RetweetProtectedStatusWarnFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
@ -1886,7 +1883,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
private class PreviewGridOnStartDragListener(private val activity: ComposeActivity) : SimpleItemTouchHelperCallback.OnStartDragListener {
override fun onStartDrag(viewHolder: ViewHolder) {
val helper = activity.mItemTouchHelper ?: return
val helper = activity.itemTouchHelper ?: return
helper.startDrag(viewHolder)
}
}

View File

@ -684,7 +684,8 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
while (i < j) {
val tab = pagerAdapter!!.getTab(i)
if (tabType == CustomTabUtils.getTabTypeAlias(tab.type)) {
if (tab.args != null && CustomTabUtils.hasAccountId(this, tab.args,
val args = tab.args
if (args != null && CustomTabUtils.hasAccountId(this, args,
activatedAccountKeys, accountKey)) {
initialTab = i
break

View File

@ -21,12 +21,9 @@ package org.mariotaku.twidere.activity
import android.app.Activity
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import org.mariotaku.twidere.BuildConfig
import org.mariotaku.twidere.util.StrictModeUtils
import org.mariotaku.twidere.util.ThemeUtils
import org.mariotaku.twidere.util.Utils
open class MainActivity : Activity() {
@ -47,9 +44,4 @@ open class MainActivity : Activity() {
finish()
}
override fun onConfigurationChanged(newConfig: Configuration) {
ThemeUtils.fixNightMode(resources, newConfig)
super.onConfigurationChanged(newConfig)
}
}

View File

@ -496,10 +496,11 @@ class SettingsWizardActivity : BaseActivity() {
values.put(Tabs.TYPE, type)
values.put(Tabs.ARGUMENTS, InternalParseUtils.bundleToJSON(spec.args))
values.put(Tabs.NAME, ParseUtils.parseString(spec.name))
if (spec.icon is Int) {
values.put(Tabs.ICON, CustomTabUtils.findTabIconKey(spec.icon))
} else if (spec.icon is File) {
values.put(Tabs.ICON, spec.icon.path)
val icon = spec.icon
if (icon is Int) {
values.put(Tabs.ICON, CustomTabUtils.findTabIconKey(icon))
} else if (icon is File) {
values.put(Tabs.ICON, icon.path)
}
values.put(Tabs.POSITION, i++)
}

View File

@ -0,0 +1,160 @@
/*
* 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.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import com.mobeta.android.dslv.SimpleDragSortCursorAdapter
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.iface.IBaseAdapter
import org.mariotaku.twidere.model.ParcelableAccount
import org.mariotaku.twidere.model.ParcelableAccountCursorIndices
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableAccountUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts
import org.mariotaku.twidere.util.JsonSerializer
import org.mariotaku.twidere.util.MediaLoaderWrapper
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.view.holder.AccountViewHolder
import javax.inject.Inject
class AccountsAdapter(context: Context) : SimpleDragSortCursorAdapter(context,
R.layout.list_item_account, null, arrayOf(Accounts.NAME),
intArrayOf(android.R.id.text1), 0), IBaseAdapter {
@Inject
lateinit override var mediaLoader: MediaLoaderWrapper
override var isProfileImageDisplayed: Boolean = false
private var sortEnabled: Boolean = false
private var indices: ParcelableAccountCursorIndices? = null
private var switchEnabled: Boolean = false
private var onAccountToggleListener: OnAccountToggleListener? = null
private val mCheckedChangeListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
val tag = buttonView.tag
if (tag !is String) return@OnCheckedChangeListener
val accountKey = UserKey.valueOf(tag) ?: return@OnCheckedChangeListener
onAccountToggleListener?.onAccountToggle(accountKey, isChecked)
}
init {
GeneralComponentHelper.build(context).inject(this)
}
fun getAccount(position: Int): ParcelableAccount? {
val c = cursor
if (c == null || c.isClosed || !c.moveToPosition(position)) return null
return indices!!.newObject(c)
}
override fun bindView(view: View, context: Context?, cursor: Cursor) {
val indices = indices!!
val color = cursor.getInt(indices.color)
val holder = view.tag as AccountViewHolder
holder.screenName.text = String.format("@%s", cursor.getString(indices.screen_name))
holder.setAccountColor(color)
if (isProfileImageDisplayed) {
val user = JsonSerializer.parse(cursor.getString(indices.account_user), ParcelableUser::class.java)
if (user != null) {
mediaLoader.displayProfileImage(holder.profileImage, user)
} else {
mediaLoader.displayProfileImage(holder.profileImage,
cursor.getString(indices.profile_image_url))
}
} else {
mediaLoader.cancelDisplayTask(holder.profileImage)
}
val accountType = cursor.getString(indices.account_type)
holder.accountType.setImageResource(ParcelableAccountUtils.getAccountTypeIcon(accountType))
holder.toggle.isChecked = cursor.getShort(indices.is_activated).toInt() == 1
holder.toggle.setOnCheckedChangeListener(mCheckedChangeListener)
holder.toggle.tag = cursor.getString(indices.account_key)
holder.toggleContainer.visibility = if (switchEnabled) View.VISIBLE else View.GONE
holder.setSortEnabled(sortEnabled)
super.bindView(view, context, cursor)
}
override fun newView(context: Context?, cursor: Cursor?, parent: ViewGroup): View {
val view = super.newView(context, cursor, parent)
val holder = AccountViewHolder(view)
view.tag = holder
return view
}
override val linkHighlightOption: Int
get() = 0
override fun setLinkHighlightOption(option: String) {
}
override var textSize: Float
get() = 0f
set(textSize) {
}
override var isDisplayNameFirst: Boolean
get() = false
set(nameFirst) {
}
override var isShowAccountColor: Boolean
get() = false
set(show) {
}
fun setSwitchEnabled(enabled: Boolean) {
if (switchEnabled == enabled) return
switchEnabled = enabled
notifyDataSetChanged()
}
fun setOnAccountToggleListener(listener: OnAccountToggleListener) {
onAccountToggleListener = listener
}
override fun swapCursor(cursor: Cursor?): Cursor? {
if (cursor != null) {
indices = ParcelableAccountCursorIndices(cursor)
}
return super.swapCursor(cursor)
}
fun setSortEnabled(sortEnabled: Boolean) {
if (this.sortEnabled == sortEnabled) return
this.sortEnabled = sortEnabled
notifyDataSetChanged()
}
interface OnAccountToggleListener {
fun onAccountToggle(accountId: UserKey, state: Boolean)
}
}

View File

@ -0,0 +1,129 @@
/*
* 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.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants
import org.mariotaku.twidere.constant.SharedPreferenceConstants
import org.mariotaku.twidere.model.ParcelableCredentials
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 @JvmOverloads constructor(context: Context, itemViewResource: Int = R.layout.list_item_user) : ArrayAdapter<ParcelableCredentials>(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<ParcelableCredentials>) : this(context) {
addAll(accounts)
}
override fun getItemId(position: Int): Long {
return getItem(position).hashCode().toLong()
}
override fun getDropDownView(position: Int, convertView: View, parent: ViewGroup): View {
val view = super.getDropDownView(position, convertView, parent)
bindView(view, getItem(position))
return view
}
override fun getView(position: Int, convertView: View, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
bindView(view, getItem(position))
return view
}
private fun bindView(view: View, item: ParcelableCredentials) {
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?
if (!item.is_dummy) {
if (text1 != null) {
text1.visibility = View.VISIBLE
text1.text = item.name
}
if (text2 != null) {
text2.visibility = View.VISIBLE
text2.text = String.format("@%s", item.screen_name)
}
if (icon != null) {
icon.visibility = View.VISIBLE
if (displayProfileImage) {
mediaLoader.displayProfileImage(icon, item)
} else {
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
}
}
}
fun setDummyItemText(textRes: Int) {
setDummyItemText(context.getString(textRes))
}
fun setDummyItemText(text: String) {
dummyItemText = text
notifyDataSetChanged()
}
fun findPositionByKey(key: UserKey): Int {
var i = 0
val j = count
while (i < j) {
if (key == getItem(i).account_key) {
return i
}
i++
}
return -1
}
}

View File

@ -0,0 +1,60 @@
package org.mariotaku.twidere.adapter
import android.content.Context
import android.support.v7.widget.RecyclerView.ViewHolder
import java.util.*
/**
* Created by mariotaku on 14/10/27.
*/
abstract class ArrayRecyclerAdapter<T, H : ViewHolder>(context: Context) : BaseRecyclerViewAdapter<H>(context) {
protected val data = ArrayList<T>()
override fun onBindViewHolder(holder: H, position: Int) {
onBindViewHolder(holder, position, getItem(position))
}
abstract fun onBindViewHolder(holder: H, position: Int, item: T)
fun add(item: T?) {
if (item == null) return
data.add(item)
notifyDataSetChanged()
}
fun addAll(collection: Collection<T>) {
data.addAll(collection)
notifyDataSetChanged()
}
fun clear() {
data.clear()
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return data.size
}
fun getItem(position: Int): T {
return data[position]
}
open fun remove(position: Int): Boolean {
data.removeAt(position)
notifyItemRemoved(position)
return true
}
fun removeAll(collection: List<T>) {
data.removeAll(collection)
notifyDataSetChanged()
}
fun sort(comparator: Comparator<in T>) {
Collections.sort(data, comparator)
notifyDataSetChanged()
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.adapter.iface.IBaseAdapter
import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import javax.inject.Inject
open class BaseArrayAdapter<T> @JvmOverloads constructor(context: Context, layoutRes: Int, collection: Collection<T>? = null) : ArrayAdapter<T>(context, layoutRes, collection), Constants, IBaseAdapter, OnSharedPreferenceChangeListener {
val linkify: TwidereLinkify
@Inject
lateinit var userColorNameManager: UserColorNameManager
@Inject
lateinit override var mediaLoader: MediaLoaderWrapper
@Inject
lateinit var multiSelectManager: MultiSelectManager
@Inject
lateinit var preferences: SharedPreferencesWrapper
private val nicknamePrefs: SharedPreferences
private val colorPrefs: SharedPreferences
override var textSize: Float = 0f
override var linkHighlightOption: Int = 0
override var isProfileImageDisplayed: Boolean = false
override var isDisplayNameFirst: Boolean = false
override var isShowAccountColor: Boolean = false
init {
//noinspection unchecked
GeneralComponentHelper.build(context).inject(this as BaseArrayAdapter<Any>)
val app = TwidereApplication.getInstance(context)
linkify = TwidereLinkify(OnLinkClickHandler(context, multiSelectManager, preferences))
nicknamePrefs = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE)
colorPrefs = context.getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE)
nicknamePrefs.registerOnSharedPreferenceChangeListener(this)
colorPrefs.registerOnSharedPreferenceChangeListener(this)
}
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
when (key) {
KEY_DISPLAY_PROFILE_IMAGE, KEY_MEDIA_PREVIEW_STYLE, KEY_DISPLAY_SENSITIVE_CONTENTS -> {
notifyDataSetChanged()
}
}
}
override fun setLinkHighlightOption(option: String) {
val optionInt = Utils.getLinkHighlightingStyleInt(option)
linkify.setHighlightOption(optionInt)
if (optionInt == linkHighlightOption) return
linkHighlightOption = optionInt
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.text.TextUtils
import android.view.View
import android.view.ViewGroup
import org.mariotaku.twidere.R
import org.mariotaku.twidere.loader.ExtensionsListLoader.ExtensionInfo
import org.mariotaku.twidere.util.PermissionsManager
import org.mariotaku.twidere.view.holder.CheckableTwoLineWithIconViewHolder
class ExtensionsAdapter(context: Context) : ArrayAdapter<ExtensionInfo>(context, R.layout.list_item_two_line_checked) {
private val mPermissionsManager: PermissionsManager
init {
mPermissionsManager = PermissionsManager(context)
}
override fun getItemId(position: Int): Long {
return getItem(position).hashCode().toLong()
}
override fun getView(position: Int, convertView: View, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
val holder: CheckableTwoLineWithIconViewHolder
val tag = view.tag
if (tag is CheckableTwoLineWithIconViewHolder) {
holder = tag
} else {
holder = CheckableTwoLineWithIconViewHolder(view)
view.tag = holder
}
val info = getItem(position)
val permissionValid = PermissionsManager.isPermissionValid(*info.permissions)
holder.checkbox.visibility = if (permissionValid) View.VISIBLE else View.GONE
if (permissionValid) {
holder.checkbox.isChecked = mPermissionsManager.checkPermission(info.pname, *info.permissions)
}
holder.text1.text = info.label
holder.text2.visibility = if (TextUtils.isEmpty(info.description)) View.GONE else View.VISIBLE
holder.text2.text = info.description
holder.icon.setImageDrawable(info.icon)
return view
}
fun setData(data: List<ExtensionInfo>?) {
clear()
if (data != null) {
addAll(data)
}
notifyDataSetChanged()
}
}

View File

@ -0,0 +1,87 @@
/*
* 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.view.View
import android.view.ViewGroup
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.iface.IBaseAdapter
import org.mariotaku.twidere.model.ParcelableUserList
import org.mariotaku.twidere.util.Utils.configBaseAdapter
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder
class SimpleParcelableUserListsAdapter(
context: Context
) : BaseArrayAdapter<ParcelableUserList>(context, R.layout.list_item_two_line), IBaseAdapter {
init {
configBaseAdapter(context, this)
}
fun appendData(data: List<ParcelableUserList>) {
setData(data, false)
}
override fun getItemId(position: Int): Long {
return (if (getItem(position) != null) getItem(position).hashCode() else -1).toLong()
}
override fun getView(position: Int, convertView: View, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
val tag = view.tag
val holder: TwoLineWithIconViewHolder
if (tag is TwoLineWithIconViewHolder) {
holder = tag
} else {
holder = TwoLineWithIconViewHolder(view)
view.tag = holder
}
// Clear images in order to prevent images in recycled view shown.
holder.icon.setImageDrawable(null)
val user_list = getItem(position)
val display_name = userColorNameManager.getDisplayName(user_list, isDisplayNameFirst)
holder.text1.text = user_list.name
holder.text2.text = context.getString(R.string.created_by, display_name)
holder.icon.visibility = if (isProfileImageDisplayed) View.VISIBLE else View.GONE
if (isProfileImageDisplayed) {
mediaLoader.displayProfileImage(holder.icon, user_list.user_profile_image_url)
} else {
mediaLoader.cancelDisplayTask(holder.icon)
}
return view
}
fun setData(data: List<ParcelableUserList>?, clearOld: Boolean) {
if (clearOld) {
clear()
}
if (data == null) return
for (user in data) {
//TODO improve compare
if (clearOld || findItemPosition(user.hashCode().toLong()) < 0) {
add(user)
}
}
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.view.View
import android.view.ViewGroup
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.iface.IBaseAdapter
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.Utils.configBaseAdapter
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder
class SimpleParcelableUsersAdapter @JvmOverloads constructor(
context: Context,
layoutRes: Int = R.layout.list_item_user
) : BaseArrayAdapter<ParcelableUser>(context, layoutRes), IBaseAdapter {
init {
configBaseAdapter(context, this)
}
override fun getItemId(position: Int): Long {
val item = getItem(position)
if (item != null) {
return item.hashCode().toLong()
} else {
return -1
}
}
override fun getView(position: Int, convertView: View, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
val tag = view.tag
val holder: TwoLineWithIconViewHolder
if (tag is TwoLineWithIconViewHolder) {
holder = tag
} else {
holder = TwoLineWithIconViewHolder(view)
view.tag = holder
}
val user = getItem(position)
holder.text1.setCompoundDrawablesWithIntrinsicBounds(0, 0,
getUserTypeIconRes(user.is_verified, user.is_protected), 0)
holder.text1.text = userColorNameManager.getUserNickname(user.key, user.name)
holder.text2.text = String.format("@%s", user.screen_name)
holder.icon.visibility = if (isProfileImageDisplayed) View.VISIBLE else View.GONE
if (isProfileImageDisplayed) {
mediaLoader.displayProfileImage(holder.icon, user)
} else {
mediaLoader.cancelDisplayTask(holder.icon)
}
return view
}
@JvmOverloads fun setData(data: List<ParcelableUser>?, clearOld: Boolean = false) {
if (clearOld) {
clear()
}
if (data == null) return
for (user in data) {
if (clearOld || findUserPosition(user.key) < 0) {
add(user)
}
}
}
fun findUserPosition(userKey: UserKey): Int {
var i = 0
val j = count
while (i < j) {
if (userKey == getItem(i).key) return i
i++
}
return -1
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.database.sqlite.SQLiteDatabase
import android.support.v4.widget.SimpleCursorAdapter
import android.view.View
import android.widget.TextView
import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.provider.TwidereDataStore.CachedStatuses
import org.mariotaku.twidere.util.HtmlEscapeHelper
class SourceAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context,
android.R.layout.simple_list_item_1, null, emptyArray<String>(), IntArray(0), 0) {
private val database: SQLiteDatabase
private var sourceIdx: Int = 0
init {
val app = TwidereApplication.getInstance(context)
database = app.sqLiteDatabase
}
override fun bindView(view: View, context: Context?, cursor: Cursor) {
if (isCursorClosed) return
val text1 = view.findViewById(android.R.id.text1) as TextView
text1.text = convertToString(cursor)
super.bindView(view, context, cursor)
}
override fun convertToString(cursor: Cursor?): CharSequence? {
if (isCursorClosed || sourceIdx == -1) return null
return HtmlEscapeHelper.toPlainText(cursor!!.getString(sourceIdx))
}
val isCursorClosed: Boolean
get() {
val cursor = cursor
return cursor == null || cursor.isClosed
}
override fun runQueryOnBackgroundThread(constraint: CharSequence?): Cursor {
val constraintEscaped = constraint?.toString()?.replace("_".toRegex(), "^_")
val selection: String?
val selectionArgs: Array<String>?
if (constraintEscaped != null) {
selection = "${CachedStatuses.SOURCE} LIKE '%\">'||?||'%</a>' ESCAPE '^'"
selectionArgs = arrayOf(constraintEscaped)
} else {
selection = null
selectionArgs = null
}
return database.query(true, CachedStatuses.TABLE_NAME, COLUMNS, selection, selectionArgs,
CachedStatuses.SOURCE, null, null, null)
}
override fun swapCursor(cursor: Cursor?): Cursor? {
if (cursor != null) {
sourceIdx = cursor.getColumnIndex(CachedStatuses.SOURCE)
}
return super.swapCursor(cursor)
}
companion object {
private val COLUMNS = arrayOf(CachedStatuses._ID, CachedStatuses.SOURCE)
}
}

View File

@ -0,0 +1,163 @@
/*
* 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.graphics.drawable.Drawable
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.view.PagerAdapter
import android.view.View
import android.view.ViewGroup
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback
import org.mariotaku.twidere.model.SupportTabSpec
import org.mariotaku.twidere.util.CustomTabUtils.getTabIconDrawable
import org.mariotaku.twidere.util.Utils.announceForAccessibilityCompat
import org.mariotaku.twidere.view.iface.PagerIndicator
import org.mariotaku.twidere.view.iface.PagerIndicator.TabListener
import org.mariotaku.twidere.view.iface.PagerIndicator.TabProvider
import java.util.*
class SupportTabsAdapter @JvmOverloads constructor(
private val context: Context,
fm: FragmentManager,
private val indicator: PagerIndicator? = null,
private val columns: Int = 1
) : SupportFixedFragmentStatePagerAdapter(fm), TabProvider, TabListener {
private val mTabs = ArrayList<SupportTabSpec>()
init {
clear()
}
fun addTab(cls: Class<out Fragment>, args: Bundle?, name: String,
icon: Int?, position: Int, tag: String?) {
addTab(SupportTabSpec(name = name, icon = icon, cls = cls, args = args,
position = position, tag = tag))
}
fun addTab(cls: Class<out Fragment>, args: Bundle?, name: String,
icon: Int?, type: String, position: Int, tag: String?) {
addTab(SupportTabSpec(name, icon, type, cls, args, position, tag))
}
fun addTab(spec: SupportTabSpec) {
mTabs.add(spec)
notifyDataSetChanged()
}
fun addTabs(specs: Collection<SupportTabSpec>) {
mTabs.addAll(specs)
notifyDataSetChanged()
}
fun clear() {
mTabs.clear()
notifyDataSetChanged()
}
override fun getCount(): Int {
return mTabs.size
}
override fun getItemPosition(`object`: Any?): Int {
if (`object` !is Fragment) return PagerAdapter.POSITION_NONE
val args = `object`.arguments ?: return PagerAdapter.POSITION_NONE
return args.getInt(EXTRA_ADAPTER_POSITION, PagerAdapter.POSITION_NONE)
}
override fun notifyDataSetChanged() {
super.notifyDataSetChanged()
indicator?.notifyDataSetChanged()
}
override fun getPageTitle(position: Int): CharSequence? {
return mTabs[position].name
}
override fun getPageWidth(position: Int): Float {
return 1.0f / columns
}
override fun getItem(position: Int): Fragment {
val fragment = Fragment.instantiate(context, mTabs[position].cls.name)
fragment.arguments = getPageArguments(mTabs[position], position)
return fragment
}
override fun startUpdate(container: ViewGroup) {
super.startUpdate(container)
}
override fun getPageIcon(position: Int): Drawable {
return getTabIconDrawable(context, mTabs[position].icon)
}
fun getTab(position: Int): SupportTabSpec {
return mTabs[position]
}
val tabs: List<SupportTabSpec>
get() = mTabs
override fun onPageReselected(position: Int) {
if (context !is SupportFragmentCallback) return
val f = context.currentVisibleFragment
if (f is RefreshScrollTopInterface) {
f.scrollToStart()
}
}
override fun onPageSelected(position: Int) {
if (indicator == null || position < 0 || position >= count) return
announceForAccessibilityCompat(context, indicator as View?, getPageTitle(position), javaClass)
}
override fun onTabLongClick(position: Int): Boolean {
if (context !is SupportFragmentCallback) return false
if (context.triggerRefresh(position)) return true
val f = context.currentVisibleFragment
if (f is RefreshScrollTopInterface)
return f.triggerRefresh()
return false
}
fun setTabLabel(position: Int, label: CharSequence) {
for (spec in mTabs) {
if (position == spec.position)
spec.name = label
}
notifyDataSetChanged()
}
private fun getPageArguments(spec: SupportTabSpec, position: Int): Bundle {
val args = spec.args ?: Bundle()
args.putInt(EXTRA_ADAPTER_POSITION, position)
return args
}
companion object {
private val EXTRA_ADAPTER_POSITION = "adapter_position"
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.adapter
import android.content.Context
import android.database.Cursor
import android.support.v4.widget.SimpleCursorAdapter
import org.mariotaku.twidere.provider.TwidereDataStore
/**
* Created by mariotaku on 15/4/29.
*/
class TrendsAdapter(context: Context) : SimpleCursorAdapter(context,
android.R.layout.simple_list_item_1, null, arrayOf(TwidereDataStore.CachedTrends.NAME),
intArrayOf(android.R.id.text1), 0) {
private var nameIdx: Int = 0
override fun getItem(position: Int): String? {
val c = cursor
if (c != null && !c.isClosed && c.moveToPosition(position))
return c.getString(nameIdx)
return null
}
override fun swapCursor(c: Cursor?): Cursor? {
if (c != null) {
nameIdx = c.getColumnIndex(TwidereDataStore.CachedTrends.NAME)
}
return super.swapCursor(c)
}
}

View File

@ -0,0 +1,141 @@
/*
* 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.adapter
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.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.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
import org.mariotaku.twidere.util.MediaLoaderWrapper
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 javax.inject.Inject
class UserAutoCompleteAdapter(context: Context) : SimpleCursorAdapter(context, R.layout.list_item_auto_complete, null, UserAutoCompleteAdapter.FROM, UserAutoCompleteAdapter.TO, 0) {
@Inject
lateinit var profileImageLoader: MediaLoaderWrapper
@Inject
lateinit var mPreferences: SharedPreferencesWrapper
@Inject
lateinit var mUserColorNameManager: UserColorNameManager
private val mDisplayProfileImage: Boolean
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
init {
GeneralComponentHelper.build(context).inject(this)
mDisplayProfileImage = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true)
}
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 ImageView
// Clear images in order to prevent images in recycled view shown.
icon.setImageDrawable(null)
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)
profileImageLoader.displayProfileImage(icon, profileImageUrl)
} else {
profileImageLoader.cancelDisplayTask(icon)
}
icon.visibility = if (mDisplayProfileImage) 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 {
return cursor!!.getString(mScreenNameIdx)
}
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
if (TextUtils.isEmpty(constraint)) return null
val filter = filterQueryProvider
if (filter != null) return filter.runQuery(constraint)
val query = constraint.toString()
val queryEscaped = query.replace("_", "^_")
val nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager)
val usersSelection = Expression.or(
Expression.likeRaw(Columns.Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(Columns.Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.inArgs(Columns.Column(CachedUsers.USER_KEY), nicknameKeys.size))
val selectionArgs = arrayOf(queryEscaped, queryEscaped, *nicknameKeys)
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,
selectionArgs, orderBy.sql)
}
fun setAccountKey(accountKey: UserKey) {
mAccountKey = 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)
}
return super.swapCursor(cursor)
}
companion object {
private val FROM = arrayOfNulls<String>(0)
private val TO = IntArray(0)
}
}

View File

@ -25,7 +25,7 @@ import org.mariotaku.twidere.util.MediaLoaderWrapper
interface IBaseAdapter : ListAdapter {
val imageLoader: MediaLoaderWrapper
val mediaLoader: MediaLoaderWrapper
val linkHighlightOption: Int
@ -33,13 +33,11 @@ interface IBaseAdapter : ListAdapter {
var isDisplayNameFirst: Boolean
val isProfileImageDisplayed: Boolean
var isProfileImageDisplayed: Boolean
var isShowAccountColor: Boolean
fun notifyDataSetChanged()
fun setDisplayProfileImage(display: Boolean)
fun setLinkHighlightOption(option: String)
}

View File

@ -38,5 +38,5 @@ interface IDirectMessagesAdapter {
@CardMediaContainer.PreviewStyle
val mediaPreviewStyle: Int
fun findItem(id: Long): ParcelableDirectMessage
fun findItem(id: Long): ParcelableDirectMessage?
}

View File

@ -560,8 +560,7 @@ abstract class AbsStatusesFragment protected constructor() : AbsContentListRecyc
@Subscribe
fun notifyStatusListChanged(event: StatusListChangedEvent) {
val adapter = adapter
adapter!!.notifyDataSetChanged()
adapter?.notifyDataSetChanged()
}
}