mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-01 09:16:47 +01:00
migrating to kotlin
This commit is contained in:
parent
b83ad85c95
commit
7319655443
@ -1,354 +0,0 @@
|
||||
package org.mariotaku.twidere.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.util.SimpleArrayMap;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mobeta.android.dslv.DragSortListView;
|
||||
import com.mobeta.android.dslv.DragSortListView.DropListener;
|
||||
|
||||
import org.mariotaku.sqliteqb.library.ArgsArray;
|
||||
import org.mariotaku.sqliteqb.library.Columns;
|
||||
import org.mariotaku.sqliteqb.library.Expression;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.ColorPickerDialogActivity;
|
||||
import org.mariotaku.twidere.activity.SignInActivity;
|
||||
import org.mariotaku.twidere.adapter.AccountsAdapter;
|
||||
import org.mariotaku.twidere.annotation.Referral;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Inbox;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Outbox;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Mentions;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
import org.mariotaku.twidere.util.IntentUtils;
|
||||
import org.mariotaku.twidere.util.TwidereCollectionUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.collection.CompactHashSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_ALPHA_SLIDER;
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_COLOR;
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_ID;
|
||||
import static org.mariotaku.twidere.Constants.INTENT_ACTION_TWITTER_LOGIN;
|
||||
import static org.mariotaku.twidere.Constants.KEY_DEFAULT_ACCOUNT_KEY;
|
||||
import static org.mariotaku.twidere.Constants.KEY_NEW_DOCUMENT_API;
|
||||
import static org.mariotaku.twidere.Constants.REQUEST_SET_COLOR;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/10/26.
|
||||
*/
|
||||
public class AccountsManagerFragment extends BaseSupportFragment implements LoaderCallbacks<Cursor>,
|
||||
DropListener, OnSharedPreferenceChangeListener, AdapterView.OnItemClickListener, AccountsAdapter.OnAccountToggleListener {
|
||||
|
||||
private static final String FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion";
|
||||
|
||||
private AccountsAdapter mAdapter;
|
||||
private ParcelableAccount mSelectedAccount;
|
||||
private SimpleArrayMap<UserKey, Boolean> mActivatedState = new SimpleArrayMap<>();
|
||||
|
||||
private DragSortListView mListView;
|
||||
private View mEmptyView;
|
||||
private View mListContainer, mProgressContainer;
|
||||
private TextView mEmptyText;
|
||||
private ImageView mEmptyIcon;
|
||||
|
||||
|
||||
private void setListShown(boolean shown) {
|
||||
mListContainer.setVisibility(shown ? View.VISIBLE : View.GONE);
|
||||
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.add_account: {
|
||||
final Intent intent = new Intent(INTENT_ACTION_TWITTER_LOGIN);
|
||||
intent.setClass(getActivity(), SignInActivity.class);
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_SET_COLOR: {
|
||||
if (resultCode != Activity.RESULT_OK || data == null || mSelectedAccount == null)
|
||||
return;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Accounts.COLOR, data.getIntExtra(EXTRA_COLOR, Color.WHITE));
|
||||
final Expression where = Expression.equalsArgs(Accounts.ACCOUNT_KEY);
|
||||
final String[] whereArgs = {mSelectedAccount.account_key.toString()};
|
||||
final ContentResolver cr = getContentResolver();
|
||||
cr.update(Accounts.CONTENT_URI, values, where.getSQL(), whereArgs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_accounts_manager, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
final ContextMenuInfo menuInfo = item.getMenuInfo();
|
||||
if (!(menuInfo instanceof AdapterContextMenuInfo)) return false;
|
||||
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
||||
ParcelableAccount account = mAdapter.getAccount(info.position);
|
||||
mSelectedAccount = account;
|
||||
if (account == null) return false;
|
||||
switch (item.getItemId()) {
|
||||
case R.id.set_color: {
|
||||
final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class);
|
||||
intent.putExtra(EXTRA_COLOR, account.color);
|
||||
intent.putExtra(EXTRA_ALPHA_SLIDER, false);
|
||||
startActivityForResult(intent, REQUEST_SET_COLOR);
|
||||
break;
|
||||
}
|
||||
case R.id.delete: {
|
||||
final AccountDeletionDialogFragment f = new AccountDeletionDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putLong(EXTRA_ID, account.id);
|
||||
f.setArguments(args);
|
||||
f.show(getChildFragmentManager(), FRAGMENT_TAG_ACCOUNT_DELETION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final Context context = getContext();
|
||||
if (context == null) return;
|
||||
final ParcelableAccount account = mAdapter.getAccount(position);
|
||||
if (account.account_user != null) {
|
||||
IntentUtils.openUserProfile(context, account.account_user, null,
|
||||
preferences.getBoolean(KEY_NEW_DOCUMENT_API),
|
||||
Referral.SELF_PROFILE);
|
||||
} else {
|
||||
IntentUtils.openUserProfile(context, account.account_key, account.account_key,
|
||||
account.screen_name, null, preferences.getBoolean(KEY_NEW_DOCUMENT_API),
|
||||
Referral.SELF_PROFILE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
saveActivatedState();
|
||||
}
|
||||
|
||||
private void saveActivatedState() {
|
||||
final Set<UserKey> trueIds = new CompactHashSet<>(), falseIds = new CompactHashSet<>();
|
||||
for (int i = 0, j = mActivatedState.size(); i < j; i++) {
|
||||
if (mActivatedState.valueAt(i)) {
|
||||
trueIds.add(mActivatedState.keyAt(i));
|
||||
} else {
|
||||
falseIds.add(mActivatedState.keyAt(i));
|
||||
}
|
||||
}
|
||||
final ContentResolver cr = getContentResolver();
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Accounts.IS_ACTIVATED, true);
|
||||
Expression where = Expression.in(new Columns.Column(Accounts.ACCOUNT_KEY), new ArgsArray(trueIds.size()));
|
||||
String[] whereArgs = TwidereCollectionUtils.toStringArray(trueIds);
|
||||
cr.update(Accounts.CONTENT_URI, values, where.getSQL(), whereArgs);
|
||||
values.put(Accounts.IS_ACTIVATED, false);
|
||||
where = Expression.in(new Columns.Column(Accounts.ACCOUNT_KEY), new ArgsArray(falseIds.size()));
|
||||
whereArgs = TwidereCollectionUtils.toStringArray(falseIds);
|
||||
cr.update(Accounts.CONTENT_URI, values, where.getSQL(), whereArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccountToggle(UserKey accountId, boolean state) {
|
||||
mActivatedState.put(accountId, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mListView = (DragSortListView) view.findViewById(android.R.id.list);
|
||||
mEmptyView = view.findViewById(android.R.id.empty);
|
||||
mEmptyIcon = (ImageView) view.findViewById(R.id.empty_icon);
|
||||
mEmptyText = (TextView) view.findViewById(R.id.empty_text);
|
||||
mListContainer = view.findViewById(R.id.list_container);
|
||||
mProgressContainer = view.findViewById(R.id.progress_container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||
if (!(menuInfo instanceof AdapterContextMenuInfo)) return;
|
||||
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
||||
final ParcelableAccount account = mAdapter.getAccount(info.position);
|
||||
menu.setHeaderTitle(account.name);
|
||||
final MenuInflater inflater = new MenuInflater(v.getContext());
|
||||
inflater.inflate(R.menu.action_manager_account, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
preferences.unregisterOnSharedPreferenceChangeListener(this);
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
final FragmentActivity activity = getActivity();
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
mAdapter = new AccountsAdapter(activity);
|
||||
Utils.configBaseAdapter(activity, mAdapter);
|
||||
mAdapter.setSortEnabled(true);
|
||||
mAdapter.setSwitchEnabled(true);
|
||||
mAdapter.setOnAccountToggleListener(this);
|
||||
mListView.setAdapter(mAdapter);
|
||||
mListView.setDragEnabled(true);
|
||||
mListView.setDropListener(this);
|
||||
mListView.setOnItemClickListener(this);
|
||||
mListView.setOnCreateContextMenuListener(this);
|
||||
mListView.setEmptyView(mEmptyView);
|
||||
mEmptyText.setText(R.string.no_account);
|
||||
mEmptyIcon.setImageResource(R.drawable.ic_info_error_generic);
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
setListShown(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.layout_draggable_list_with_empty_view, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
final Uri uri = Accounts.CONTENT_URI;
|
||||
return new CursorLoader(getActivity(), uri, Accounts.COLUMNS, null, null, Accounts.SORT_POSITION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
setListShown(true);
|
||||
mAdapter.changeCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
mAdapter.changeCursor(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drop(int from, int to) {
|
||||
mAdapter.drop(from, to);
|
||||
if (mListView.getChoiceMode() != AbsListView.CHOICE_MODE_NONE) {
|
||||
mListView.moveCheckState(from, to);
|
||||
}
|
||||
saveAccountPositions();
|
||||
}
|
||||
|
||||
private void saveAccountPositions() {
|
||||
final ContentResolver cr = getContentResolver();
|
||||
final ArrayList<Integer> positions = mAdapter.getCursorPositions();
|
||||
final Cursor c = mAdapter.getCursor();
|
||||
if (positions != null && c != null && !c.isClosed()) {
|
||||
final int idIdx = c.getColumnIndex(Accounts._ID);
|
||||
for (int i = 0, j = positions.size(); i < j; i++) {
|
||||
c.moveToPosition(positions.get(i));
|
||||
final long id = c.getLong(idIdx);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Accounts.SORT_POSITION, i);
|
||||
final Expression where = Expression.equals(Accounts._ID, id);
|
||||
cr.update(Accounts.CONTENT_URI, values, where.getSQL(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (KEY_DEFAULT_ACCOUNT_KEY.equals(key)) {
|
||||
updateDefaultAccount();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDefaultAccount() {
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public static final class AccountDeletionDialogFragment extends BaseDialogFragment implements
|
||||
DialogInterface.OnClickListener {
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final Bundle args = getArguments();
|
||||
final long id = args.getLong(EXTRA_ID);
|
||||
final ContentResolver resolver = getContentResolver();
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
final String where = Expression.equalsArgs(Accounts._ID)
|
||||
.getSQL();
|
||||
final String[] whereArgs = {String.valueOf(id)};
|
||||
resolver.delete(Accounts.CONTENT_URI, where, whereArgs);
|
||||
// Also delete tweets related to the account we previously
|
||||
// deleted.
|
||||
resolver.delete(Statuses.CONTENT_URI, where, whereArgs);
|
||||
resolver.delete(Mentions.CONTENT_URI, where, whereArgs);
|
||||
resolver.delete(Inbox.CONTENT_URI, where, whereArgs);
|
||||
resolver.delete(Outbox.CONTENT_URI, where, whereArgs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context context = getContext();
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setTitle(R.string.account_delete_confirm_title);
|
||||
builder.setMessage(R.string.account_delete_confirm_message);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,255 +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.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import com.twitter.Extractor;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableUserMention;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
||||
import org.mariotaku.twidere.util.HtmlEscapeHelper;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.UserColorNameManager;
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AddStatusFilterDialogFragment extends BaseDialogFragment {
|
||||
|
||||
public static final String FRAGMENT_TAG = "add_status_filter";
|
||||
|
||||
private final Extractor mExtractor = new Extractor();
|
||||
private FilterItemInfo[] mFilterItems;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
mFilterItems = getFilterItemsInfo();
|
||||
final String[] entries = new String[mFilterItems.length];
|
||||
final boolean nameFirst = preferences.getBoolean(KEY_NAME_FIRST);
|
||||
for (int i = 0, j = entries.length; i < j; i++) {
|
||||
final FilterItemInfo info = mFilterItems[i];
|
||||
switch (info.type) {
|
||||
case FilterItemInfo.FILTER_TYPE_USER:
|
||||
entries[i] = getString(R.string.user_filter_name, getName(userColorNameManager,
|
||||
info.value, nameFirst));
|
||||
break;
|
||||
case FilterItemInfo.FILTER_TYPE_KEYWORD:
|
||||
entries[i] = getString(R.string.keyword_filter_name, getName(userColorNameManager,
|
||||
info.value, nameFirst));
|
||||
break;
|
||||
case FilterItemInfo.FILTER_TYPE_SOURCE:
|
||||
entries[i] = getString(R.string.source_filter_name, getName(userColorNameManager,
|
||||
info.value, nameFirst));
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.setTitle(R.string.add_to_filter);
|
||||
builder.setMultiChoiceItems(entries, null, null);
|
||||
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
AlertDialog alertDialog = ((AlertDialog) dialog);
|
||||
final SparseBooleanArray checkPositions = alertDialog.getListView().getCheckedItemPositions();
|
||||
|
||||
final Set<UserKey> userKeys = new HashSet<>();
|
||||
final Set<String> keywords = new HashSet<>();
|
||||
final Set<String> sources = new HashSet<>();
|
||||
final ArrayList<ContentValues> userValues = new ArrayList<>();
|
||||
final ArrayList<ContentValues> keywordValues = new ArrayList<>();
|
||||
final ArrayList<ContentValues> sourceValues = new ArrayList<>();
|
||||
for (int i = 0, j = checkPositions.size(); i < j; i++) {
|
||||
if (!checkPositions.valueAt(i)) continue;
|
||||
final FilterItemInfo info = mFilterItems[checkPositions.keyAt(i)];
|
||||
final Object value = info.value;
|
||||
if (value instanceof ParcelableUserMention) {
|
||||
final ParcelableUserMention mention = (ParcelableUserMention) value;
|
||||
userKeys.add(mention.key);
|
||||
userValues.add(ContentValuesCreator.createFilteredUser(mention));
|
||||
} else if (value instanceof UserItem) {
|
||||
final UserItem item = (UserItem) value;
|
||||
userKeys.add(item.key);
|
||||
userValues.add(createFilteredUser(item));
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_KEYWORD) {
|
||||
if (value != null) {
|
||||
final String keyword = ParseUtils.parseString(value);
|
||||
keywords.add(keyword);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Keywords.VALUE, "#" + keyword);
|
||||
keywordValues.add(values);
|
||||
}
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_SOURCE) {
|
||||
if (value != null) {
|
||||
final String source = ParseUtils.parseString(value);
|
||||
sources.add(source);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Sources.VALUE, source);
|
||||
sourceValues.add(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
final ContentResolver resolver = getContentResolver();
|
||||
ContentResolverUtils.bulkDelete(resolver, Filters.Users.CONTENT_URI, Filters.Users.USER_KEY, userKeys, null);
|
||||
ContentResolverUtils.bulkDelete(resolver, Filters.Keywords.CONTENT_URI, Filters.Keywords.VALUE, keywords, null);
|
||||
ContentResolverUtils.bulkDelete(resolver, Filters.Sources.CONTENT_URI, Filters.Sources.VALUE, sources, null);
|
||||
ContentResolverUtils.bulkInsert(resolver, Filters.Users.CONTENT_URI, userValues);
|
||||
ContentResolverUtils.bulkInsert(resolver, Filters.Keywords.CONTENT_URI, keywordValues);
|
||||
ContentResolverUtils.bulkInsert(resolver, Filters.Sources.CONTENT_URI, sourceValues);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private FilterItemInfo[] getFilterItemsInfo() {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null || !args.containsKey(EXTRA_STATUS)) return new FilterItemInfo[0];
|
||||
final ParcelableStatus status = args.getParcelable(EXTRA_STATUS);
|
||||
if (status == null) return new FilterItemInfo[0];
|
||||
final ArrayList<FilterItemInfo> list = new ArrayList<>();
|
||||
if (status.is_retweet) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, new UserItem(status.retweeted_by_user_key,
|
||||
status.retweeted_by_user_name, status.retweeted_by_user_screen_name)));
|
||||
}
|
||||
if (status.is_quote) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, new UserItem(status.quoted_user_key,
|
||||
status.quoted_user_name, status.quoted_user_screen_name)));
|
||||
}
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, new UserItem(status.user_key,
|
||||
status.user_name, status.user_screen_name)));
|
||||
final ParcelableUserMention[] mentions = status.mentions;
|
||||
if (mentions != null) {
|
||||
for (final ParcelableUserMention mention : mentions) {
|
||||
if (!mention.key.equals(status.user_key)) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, mention));
|
||||
}
|
||||
}
|
||||
}
|
||||
final HashSet<String> hashtags = new HashSet<>();
|
||||
hashtags.addAll(mExtractor.extractHashtags(status.text_plain));
|
||||
for (final String hashtag : hashtags) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_KEYWORD, hashtag));
|
||||
}
|
||||
final String source = HtmlEscapeHelper.toPlainText(status.source);
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_SOURCE, source));
|
||||
return list.toArray(new FilterItemInfo[list.size()]);
|
||||
}
|
||||
|
||||
private String getName(final UserColorNameManager manager, final Object value, boolean nameFirst) {
|
||||
if (value instanceof ParcelableUserMention) {
|
||||
final ParcelableUserMention mention = (ParcelableUserMention) value;
|
||||
return manager.getDisplayName(mention.key, mention.name, mention.screen_name, nameFirst
|
||||
);
|
||||
} else if (value instanceof UserItem) {
|
||||
final UserItem item = (UserItem) value;
|
||||
return manager.getDisplayName(item.key, item.name, item.screen_name, nameFirst);
|
||||
} else
|
||||
return ParseUtils.parseString(value);
|
||||
}
|
||||
|
||||
private static ContentValues createFilteredUser(UserItem item) {
|
||||
if (item == null) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Users.USER_KEY, item.key.toString());
|
||||
values.put(Filters.Users.NAME, item.name);
|
||||
values.put(Filters.Users.SCREEN_NAME, item.screen_name);
|
||||
return values;
|
||||
}
|
||||
|
||||
public static AddStatusFilterDialogFragment show(final FragmentManager fm, final ParcelableStatus status) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_STATUS, status);
|
||||
final AddStatusFilterDialogFragment f = new AddStatusFilterDialogFragment();
|
||||
f.setArguments(args);
|
||||
f.show(fm, FRAGMENT_TAG);
|
||||
return f;
|
||||
}
|
||||
|
||||
private static class FilterItemInfo {
|
||||
|
||||
static final int FILTER_TYPE_USER = 1;
|
||||
static final int FILTER_TYPE_KEYWORD = 2;
|
||||
static final int FILTER_TYPE_SOURCE = 3;
|
||||
|
||||
final int type;
|
||||
final Object value;
|
||||
|
||||
FilterItemInfo(final int type, final Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof FilterItemInfo)) return false;
|
||||
final FilterItemInfo other = (FilterItemInfo) obj;
|
||||
if (type != other.type) return false;
|
||||
if (value == null) {
|
||||
if (other.value != null) return false;
|
||||
} else if (!value.equals(other.value)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + type;
|
||||
result = prime * result + (value == null ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FilterItemInfo{type=" + type + ", value=" + value + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class UserItem {
|
||||
private final UserKey key;
|
||||
private final String name, screen_name;
|
||||
|
||||
public UserItem(UserKey key, String name, String screen_name) {
|
||||
this.key = key;
|
||||
this.name = name;
|
||||
this.screen_name = screen_name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,412 +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.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.content.res.ResourcesCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.ActionMode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SubMenu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AbsListView.MultiChoiceModeListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.afollestad.appthemeengine.ATEActivity;
|
||||
import com.afollestad.appthemeengine.Config;
|
||||
import com.mobeta.android.dslv.DragSortListView;
|
||||
import com.mobeta.android.dslv.DragSortListView.DropListener;
|
||||
import com.mobeta.android.dslv.SimpleDragSortCursorAdapter;
|
||||
|
||||
import org.mariotaku.sqliteqb.library.Columns.Column;
|
||||
import org.mariotaku.sqliteqb.library.Expression;
|
||||
import org.mariotaku.sqliteqb.library.RawItemArray;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.CustomTabEditorActivity;
|
||||
import org.mariotaku.twidere.activity.SettingsActivity;
|
||||
import org.mariotaku.twidere.model.CustomTabConfiguration;
|
||||
import org.mariotaku.twidere.model.CustomTabConfiguration.CustomTabConfigurationComparator;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
|
||||
import org.mariotaku.twidere.util.CustomTabUtils;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_ARGUMENTS;
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_EXTRAS;
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_ICON;
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_ID;
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_NAME;
|
||||
import static org.mariotaku.twidere.Constants.EXTRA_TYPE;
|
||||
import static org.mariotaku.twidere.Constants.INTENT_ACTION_ADD_TAB;
|
||||
import static org.mariotaku.twidere.Constants.INTENT_ACTION_EDIT_TAB;
|
||||
import static org.mariotaku.twidere.Constants.REQUEST_ADD_TAB;
|
||||
import static org.mariotaku.twidere.Constants.REQUEST_EDIT_TAB;
|
||||
|
||||
public class CustomTabsFragment extends BaseSupportFragment implements LoaderCallbacks<Cursor>,
|
||||
MultiChoiceModeListener, OnItemClickListener {
|
||||
|
||||
private ContentResolver mResolver;
|
||||
|
||||
private CustomTabsAdapter mAdapter;
|
||||
|
||||
private DragSortListView mListView;
|
||||
private View mEmptyView;
|
||||
private View mListContainer, mProgressContainer;
|
||||
private TextView mEmptyText;
|
||||
private ImageView mEmptyIcon;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.delete: {
|
||||
final long[] itemIds = mListView.getCheckedItemIds();
|
||||
final Expression where = Expression.in(new Column(Tabs._ID), new RawItemArray(itemIds));
|
||||
mResolver.delete(Tabs.CONTENT_URI, where.getSQL(), null);
|
||||
SettingsActivity.Companion.setShouldNotifyChange(getActivity());
|
||||
break;
|
||||
}
|
||||
}
|
||||
mode.finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
mResolver = getContentResolver();
|
||||
final View view = getView();
|
||||
assert view != null;
|
||||
final Context context = view.getContext();
|
||||
mAdapter = new CustomTabsAdapter(context);
|
||||
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
|
||||
mListView.setMultiChoiceModeListener(this);
|
||||
mListView.setOnItemClickListener(this);
|
||||
mListView.setAdapter(mAdapter);
|
||||
mListView.setEmptyView(mEmptyView);
|
||||
mListView.setDropListener(new DropListener() {
|
||||
@Override
|
||||
public void drop(final int from, final int to) {
|
||||
mAdapter.drop(from, to);
|
||||
if (mListView.getChoiceMode() != AbsListView.CHOICE_MODE_NONE) {
|
||||
mListView.moveCheckState(from, to);
|
||||
}
|
||||
saveTabPositions();
|
||||
}
|
||||
});
|
||||
mEmptyText.setText(R.string.no_tab);
|
||||
mEmptyIcon.setImageResource(R.drawable.ic_info_tab);
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
setListShown(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final Cursor c = mAdapter.getCursor();
|
||||
c.moveToPosition(mAdapter.getCursorPosition(position));
|
||||
final Intent intent = new Intent(INTENT_ACTION_EDIT_TAB);
|
||||
intent.setClass(getActivity(), CustomTabEditorActivity.class);
|
||||
intent.putExtra(EXTRA_ID, c.getLong(c.getColumnIndex(Tabs._ID)));
|
||||
intent.putExtra(EXTRA_TYPE, c.getString(c.getColumnIndex(Tabs.TYPE)));
|
||||
intent.putExtra(EXTRA_NAME, c.getString(c.getColumnIndex(Tabs.NAME)));
|
||||
intent.putExtra(EXTRA_ICON, c.getString(c.getColumnIndex(Tabs.ICON)));
|
||||
intent.putExtra(EXTRA_EXTRAS, c.getString(c.getColumnIndex(Tabs.EXTRAS)));
|
||||
startActivityForResult(intent, REQUEST_EDIT_TAB);
|
||||
}
|
||||
|
||||
private void setListShown(boolean shown) {
|
||||
mListContainer.setVisibility(shown ? View.VISIBLE : View.GONE);
|
||||
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mListView = (DragSortListView) view.findViewById(android.R.id.list);
|
||||
mEmptyView = view.findViewById(android.R.id.empty);
|
||||
mEmptyIcon = (ImageView) view.findViewById(R.id.empty_icon);
|
||||
mEmptyText = (TextView) view.findViewById(R.id.empty_text);
|
||||
mListContainer = view.findViewById(R.id.list_container);
|
||||
mProgressContainer = view.findViewById(R.id.progress_container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_ADD_TAB: {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Tabs.NAME, data.getStringExtra(EXTRA_NAME));
|
||||
values.put(Tabs.ICON, data.getStringExtra(EXTRA_ICON));
|
||||
values.put(Tabs.TYPE, data.getStringExtra(EXTRA_TYPE));
|
||||
values.put(Tabs.ARGUMENTS, data.getStringExtra(EXTRA_ARGUMENTS));
|
||||
values.put(Tabs.EXTRAS, data.getStringExtra(EXTRA_EXTRAS));
|
||||
values.put(Tabs.POSITION, mAdapter.getCount());
|
||||
mResolver.insert(Tabs.CONTENT_URI, values);
|
||||
SettingsActivity.Companion.setShouldNotifyChange(getActivity());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REQUEST_EDIT_TAB: {
|
||||
if (resultCode == Activity.RESULT_OK && data.hasExtra(EXTRA_ID)) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Tabs.NAME, data.getStringExtra(EXTRA_NAME));
|
||||
values.put(Tabs.ICON, data.getStringExtra(EXTRA_ICON));
|
||||
values.put(Tabs.EXTRAS, data.getStringExtra(EXTRA_EXTRAS));
|
||||
final String where = Expression.equals(Tabs._ID, data.getLongExtra(EXTRA_ID, -1)).getSQL();
|
||||
mResolver.update(Tabs.CONTENT_URI, values, where, null);
|
||||
SettingsActivity.Companion.setShouldNotifyChange(getActivity());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(final ActionMode mode, final Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.action_multi_select_items, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
|
||||
return new CursorLoader(getActivity(), Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, Tabs.DEFAULT_SORT_ORDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_custom_tabs, menu);
|
||||
final Resources res = getResources();
|
||||
final FragmentActivity activity = getActivity();
|
||||
final UserKey[] accountIds = DataStoreUtils.getAccountKeys(activity);
|
||||
final MenuItem itemAdd = menu.findItem(R.id.add_submenu);
|
||||
if (itemAdd != null && itemAdd.hasSubMenu()) {
|
||||
final SubMenu subMenu = itemAdd.getSubMenu();
|
||||
subMenu.clear();
|
||||
final HashMap<String, CustomTabConfiguration> map = CustomTabUtils.getConfigurationMap();
|
||||
final List<Entry<String, CustomTabConfiguration>> tabs = new ArrayList<>(
|
||||
map.entrySet());
|
||||
Collections.sort(tabs, CustomTabConfigurationComparator.SINGLETON);
|
||||
for (final Entry<String, CustomTabConfiguration> entry : tabs) {
|
||||
final String type = entry.getKey();
|
||||
final CustomTabConfiguration conf = entry.getValue();
|
||||
|
||||
final boolean accountIdRequired = conf.getAccountRequirement() == CustomTabConfiguration.ACCOUNT_REQUIRED;
|
||||
|
||||
final Intent intent = new Intent(INTENT_ACTION_ADD_TAB);
|
||||
intent.setClass(activity, CustomTabEditorActivity.class);
|
||||
intent.putExtra(EXTRA_TYPE, type);
|
||||
|
||||
final MenuItem subItem = subMenu.add(conf.getDefaultTitle());
|
||||
final boolean disabledByNoAccount = accountIdRequired && accountIds.length == 0;
|
||||
final boolean disabledByDuplicateTab = conf.isSingleTab() && CustomTabUtils.isTabAdded(activity, type);
|
||||
final boolean shouldDisable = disabledByDuplicateTab || disabledByNoAccount;
|
||||
subItem.setVisible(!shouldDisable);
|
||||
subItem.setEnabled(!shouldDisable);
|
||||
final Drawable icon = ResourcesCompat.getDrawable(res, conf.getDefaultIcon(), null);
|
||||
if (icon != null && activity instanceof ATEActivity) {
|
||||
icon.mutate().setColorFilter(Config.textColorPrimary(activity,
|
||||
((ATEActivity) activity).getATEKey()), Mode.SRC_ATOP);
|
||||
}
|
||||
subItem.setIcon(icon);
|
||||
subItem.setIntent(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.layout_draggable_list_with_empty_view, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(final ActionMode mode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemCheckedStateChanged(final ActionMode mode, final int position, final long id,
|
||||
final boolean checked) {
|
||||
updateTitle(mode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(final Loader<Cursor> loader) {
|
||||
mAdapter.changeCursor(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) {
|
||||
mAdapter.changeCursor(cursor);
|
||||
setListShown(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
default: {
|
||||
final Intent intent = item.getIntent();
|
||||
if (intent == null) return false;
|
||||
startActivityForResult(intent, REQUEST_ADD_TAB);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(final ActionMode mode, final Menu menu) {
|
||||
updateTitle(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
private void saveTabPositions() {
|
||||
final ArrayList<Integer> positions = mAdapter.getCursorPositions();
|
||||
final Cursor c = mAdapter.getCursor();
|
||||
if (positions != null && c != null && !c.isClosed()) {
|
||||
final int idIdx = c.getColumnIndex(Tabs._ID);
|
||||
for (int i = 0, j = positions.size(); i < j; i++) {
|
||||
c.moveToPosition(positions.get(i));
|
||||
final long id = c.getLong(idIdx);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Tabs.POSITION, i);
|
||||
final String where = Expression.equals(Tabs._ID, id).getSQL();
|
||||
mResolver.update(Tabs.CONTENT_URI, values, where, null);
|
||||
}
|
||||
}
|
||||
SettingsActivity.Companion.setShouldNotifyChange(getActivity());
|
||||
}
|
||||
|
||||
private void updateTitle(final ActionMode mode) {
|
||||
if (mListView == null || mode == null || getActivity() == null) return;
|
||||
final int count = mListView.getCheckedItemCount();
|
||||
mode.setTitle(getResources().getQuantityString(R.plurals.Nitems_selected, count, count));
|
||||
}
|
||||
|
||||
public static class CustomTabsAdapter extends SimpleDragSortCursorAdapter {
|
||||
|
||||
private final int mIconColor;
|
||||
private CursorIndices mIndices;
|
||||
|
||||
public CustomTabsAdapter(final Context context) {
|
||||
super(context, R.layout.list_item_custom_tab, null, new String[0], new int[0], 0);
|
||||
mIconColor = ThemeUtils.getThemeForegroundColor(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(final View view, final Context context, final Cursor cursor) {
|
||||
super.bindView(view, context, cursor);
|
||||
final TwoLineWithIconViewHolder holder = (TwoLineWithIconViewHolder) view.getTag();
|
||||
final String type = cursor.getString(mIndices.type);
|
||||
final String name = cursor.getString(mIndices.name);
|
||||
final String iconKey = cursor.getString(mIndices.icon);
|
||||
if (CustomTabUtils.isTabTypeValid(type)) {
|
||||
final String typeName = CustomTabUtils.getTabTypeName(context, type);
|
||||
holder.text1.setText(TextUtils.isEmpty(name) ? typeName : name);
|
||||
holder.text1.setPaintFlags(holder.text1.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
holder.text2.setVisibility(View.VISIBLE);
|
||||
holder.text2.setText(typeName);
|
||||
} else {
|
||||
holder.text1.setText(name);
|
||||
holder.text1.setPaintFlags(holder.text1.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
holder.text2.setText(R.string.invalid_tab);
|
||||
}
|
||||
final Drawable icon = CustomTabUtils.getTabIconDrawable(context, CustomTabUtils.getTabIconObject(iconKey));
|
||||
holder.icon.setVisibility(View.VISIBLE);
|
||||
if (icon != null) {
|
||||
holder.icon.setImageDrawable(icon);
|
||||
} else {
|
||||
holder.icon.setImageResource(R.drawable.ic_action_list);
|
||||
}
|
||||
holder.icon.setColorFilter(mIconColor, Mode.SRC_ATOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeCursor(final Cursor cursor) {
|
||||
if (cursor != null) {
|
||||
mIndices = new CursorIndices(cursor);
|
||||
}
|
||||
super.changeCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
|
||||
final View view = super.newView(context, cursor, parent);
|
||||
final Object tag = view.getTag();
|
||||
if (!(tag instanceof TwoLineWithIconViewHolder)) {
|
||||
final TwoLineWithIconViewHolder holder = new TwoLineWithIconViewHolder(view);
|
||||
view.setTag(holder);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
static class CursorIndices {
|
||||
final int _id, name, icon, type, arguments;
|
||||
|
||||
CursorIndices(final Cursor mCursor) {
|
||||
_id = mCursor.getColumnIndex(Tabs._ID);
|
||||
icon = mCursor.getColumnIndex(Tabs.ICON);
|
||||
name = mCursor.getColumnIndex(Tabs.NAME);
|
||||
type = mCursor.getColumnIndex(Tabs.TYPE);
|
||||
arguments = mCursor.getColumnIndex(Tabs.ARGUMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +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.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
|
||||
public class DestroyStatusDialogFragment extends BaseDialogFragment implements DialogInterface.OnClickListener {
|
||||
|
||||
public static final String FRAGMENT_TAG = "destroy_status";
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
final ParcelableStatus status = getStatus();
|
||||
final AsyncTwitterWrapper twitter = twitterWrapper;
|
||||
if (status == null) return;
|
||||
twitter.destroyStatusAsync(status.account_key, status.id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context context = getActivity();
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.destroy_status);
|
||||
builder.setMessage(R.string.destroy_status_confirm_message);
|
||||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private ParcelableStatus getStatus() {
|
||||
final Bundle args = getArguments();
|
||||
if (!args.containsKey(EXTRA_STATUS)) return null;
|
||||
return args.getParcelable(EXTRA_STATUS);
|
||||
}
|
||||
|
||||
public static DestroyStatusDialogFragment show(final FragmentManager fm, final ParcelableStatus status) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_STATUS, status);
|
||||
final DestroyStatusDialogFragment f = new DestroyStatusDialogFragment();
|
||||
f.setArguments(args);
|
||||
f.show(fm, FRAGMENT_TAG);
|
||||
return f;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.mariotaku.twidere.fragment;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/3/28.
|
||||
*/
|
||||
public class MessagesEntriesFragment extends Fragment {
|
||||
}
|
@ -0,0 +1,291 @@
|
||||
package org.mariotaku.twidere.fragment
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.app.Dialog
|
||||
import android.content.ContentValues
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||
import android.database.Cursor
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
||||
import android.support.v4.content.CursorLoader
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v4.util.SimpleArrayMap
|
||||
import android.view.*
|
||||
import android.view.ContextMenu.ContextMenuInfo
|
||||
import android.widget.AbsListView
|
||||
import android.widget.AdapterView
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo
|
||||
import com.mobeta.android.dslv.DragSortListView.DropListener
|
||||
import kotlinx.android.synthetic.main.layout_draggable_list_with_empty_view.*
|
||||
import org.mariotaku.sqliteqb.library.ArgsArray
|
||||
import org.mariotaku.sqliteqb.library.Columns
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.twidere.Constants.*
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.activity.ColorPickerDialogActivity
|
||||
import org.mariotaku.twidere.activity.SignInActivity
|
||||
import org.mariotaku.twidere.adapter.AccountsAdapter
|
||||
import org.mariotaku.twidere.annotation.Referral
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
||||
import org.mariotaku.twidere.model.ParcelableAccount
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Inbox
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Outbox
|
||||
import org.mariotaku.twidere.util.IntentUtils
|
||||
import org.mariotaku.twidere.util.TwidereCollectionUtils
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
import org.mariotaku.twidere.util.collection.CompactHashSet
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/10/26.
|
||||
*/
|
||||
class AccountsManagerFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, DropListener, OnSharedPreferenceChangeListener, AdapterView.OnItemClickListener, AccountsAdapter.OnAccountToggleListener {
|
||||
|
||||
private var adapter: AccountsAdapter? = null
|
||||
private var selectedAccount: ParcelableAccount? = null
|
||||
private val activatedState = SimpleArrayMap<UserKey, Boolean>()
|
||||
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
val activity = activity
|
||||
preferences.registerOnSharedPreferenceChangeListener(this)
|
||||
adapter = AccountsAdapter(activity)
|
||||
Utils.configBaseAdapter(activity, adapter)
|
||||
adapter!!.setSortEnabled(true)
|
||||
adapter!!.setSwitchEnabled(true)
|
||||
adapter!!.setOnAccountToggleListener(this)
|
||||
listView.adapter = adapter
|
||||
listView.isDragEnabled = true
|
||||
listView.setDropListener(this)
|
||||
listView.onItemClickListener = this
|
||||
listView.setOnCreateContextMenuListener(this)
|
||||
listView.emptyView = emptyView
|
||||
emptyText.setText(R.string.no_account)
|
||||
emptyIcon.setImageResource(R.drawable.ic_info_error_generic)
|
||||
loaderManager.initLoader(0, null, this)
|
||||
setListShown(false)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when (requestCode) {
|
||||
REQUEST_SET_COLOR -> {
|
||||
if (resultCode != Activity.RESULT_OK || data == null || selectedAccount == null)
|
||||
return
|
||||
val values = ContentValues()
|
||||
values.put(Accounts.COLOR, data.getIntExtra(EXTRA_COLOR, Color.WHITE))
|
||||
val where = Expression.equalsArgs(Accounts.ACCOUNT_KEY)
|
||||
val whereArgs = arrayOf(selectedAccount!!.account_key.toString())
|
||||
val cr = contentResolver
|
||||
cr.update(Accounts.CONTENT_URI, values, where.sql, whereArgs)
|
||||
return
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.add_account -> {
|
||||
val intent = Intent(INTENT_ACTION_TWITTER_LOGIN)
|
||||
intent.setClass(activity, SignInActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.menu_accounts_manager, menu)
|
||||
}
|
||||
|
||||
override fun onContextItemSelected(item: MenuItem?): Boolean {
|
||||
val menuInfo = item!!.menuInfo
|
||||
if (menuInfo !is AdapterContextMenuInfo) return false
|
||||
val account = adapter!!.getAccount(menuInfo.position)
|
||||
selectedAccount = account
|
||||
if (account == null) return false
|
||||
when (item.itemId) {
|
||||
R.id.set_color -> {
|
||||
val intent = Intent(activity, ColorPickerDialogActivity::class.java)
|
||||
intent.putExtra(EXTRA_COLOR, account.color)
|
||||
intent.putExtra(EXTRA_ALPHA_SLIDER, false)
|
||||
startActivityForResult(intent, REQUEST_SET_COLOR)
|
||||
}
|
||||
R.id.delete -> {
|
||||
val f = AccountDeletionDialogFragment()
|
||||
val args = Bundle()
|
||||
args.putLong(EXTRA_ID, account.id)
|
||||
f.arguments = args
|
||||
f.show(childFragmentManager, FRAGMENT_TAG_ACCOUNT_DELETION)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
|
||||
val context = context ?: return
|
||||
val account = adapter!!.getAccount(position)
|
||||
if (account!!.account_user != null) {
|
||||
IntentUtils.openUserProfile(context, account.account_user!!, null,
|
||||
preferences.getBoolean(SharedPreferenceConstants.KEY_NEW_DOCUMENT_API),
|
||||
Referral.SELF_PROFILE)
|
||||
} else {
|
||||
IntentUtils.openUserProfile(context, account.account_key, account.account_key,
|
||||
account.screen_name, null, preferences.getBoolean(SharedPreferenceConstants.KEY_NEW_DOCUMENT_API),
|
||||
Referral.SELF_PROFILE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
saveActivatedState()
|
||||
}
|
||||
|
||||
private fun saveActivatedState() {
|
||||
val trueIds = CompactHashSet<UserKey>()
|
||||
val falseIds = CompactHashSet<UserKey>()
|
||||
var i = 0
|
||||
val j = activatedState.size()
|
||||
while (i < j) {
|
||||
if (activatedState.valueAt(i)) {
|
||||
trueIds.add(activatedState.keyAt(i))
|
||||
} else {
|
||||
falseIds.add(activatedState.keyAt(i))
|
||||
}
|
||||
i++
|
||||
}
|
||||
val cr = contentResolver
|
||||
val values = ContentValues()
|
||||
values.put(Accounts.IS_ACTIVATED, true)
|
||||
var where = Expression.`in`(Columns.Column(Accounts.ACCOUNT_KEY), ArgsArray(trueIds.size))
|
||||
var whereArgs = TwidereCollectionUtils.toStringArray(trueIds)
|
||||
cr.update(Accounts.CONTENT_URI, values, where.sql, whereArgs)
|
||||
values.put(Accounts.IS_ACTIVATED, false)
|
||||
where = Expression.`in`(Columns.Column(Accounts.ACCOUNT_KEY), ArgsArray(falseIds.size))
|
||||
whereArgs = TwidereCollectionUtils.toStringArray(falseIds)
|
||||
cr.update(Accounts.CONTENT_URI, values, where.sql, whereArgs)
|
||||
}
|
||||
|
||||
override fun onAccountToggle(accountId: UserKey, state: Boolean) {
|
||||
activatedState.put(accountId, state)
|
||||
}
|
||||
|
||||
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenuInfo) {
|
||||
if (menuInfo !is AdapterContextMenuInfo) return
|
||||
val account = adapter!!.getAccount(menuInfo.position)
|
||||
menu.setHeaderTitle(account!!.name)
|
||||
val inflater = MenuInflater(v.context)
|
||||
inflater.inflate(R.menu.action_manager_account, menu)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
preferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.layout_draggable_list_with_empty_view, container, false)
|
||||
}
|
||||
|
||||
private fun setListShown(shown: Boolean) {
|
||||
listContainer.visibility = if (shown) View.VISIBLE else View.GONE
|
||||
progressContainer.visibility = if (shown) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor?> {
|
||||
val uri = Accounts.CONTENT_URI
|
||||
return CursorLoader(activity, uri, Accounts.COLUMNS, null, null, Accounts.SORT_POSITION)
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<Cursor?>, cursor: Cursor?) {
|
||||
setListShown(true)
|
||||
adapter!!.changeCursor(cursor)
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<Cursor?>) {
|
||||
adapter!!.changeCursor(null)
|
||||
}
|
||||
|
||||
override fun drop(from: Int, to: Int) {
|
||||
adapter!!.drop(from, to)
|
||||
if (listView.choiceMode != AbsListView.CHOICE_MODE_NONE) {
|
||||
listView.moveCheckState(from, to)
|
||||
}
|
||||
saveAccountPositions()
|
||||
}
|
||||
|
||||
private fun saveAccountPositions() {
|
||||
val cr = contentResolver
|
||||
val positions = adapter!!.cursorPositions
|
||||
val c = adapter!!.cursor
|
||||
if (positions != null && c != null && !c.isClosed) {
|
||||
val idIdx = c.getColumnIndex(Accounts._ID)
|
||||
var i = 0
|
||||
val j = positions.size
|
||||
while (i < j) {
|
||||
c.moveToPosition(positions[i])
|
||||
val id = c.getLong(idIdx)
|
||||
val values = ContentValues()
|
||||
values.put(Accounts.SORT_POSITION, i)
|
||||
val where = Expression.equals(Accounts._ID, id)
|
||||
cr.update(Accounts.CONTENT_URI, values, where.sql, null)
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
|
||||
if (SharedPreferenceConstants.KEY_DEFAULT_ACCOUNT_KEY == key) {
|
||||
updateDefaultAccount()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDefaultAccount() {
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
class AccountDeletionDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
|
||||
|
||||
override fun onClick(dialog: DialogInterface, which: Int) {
|
||||
val id = arguments.getLong(EXTRA_ID)
|
||||
val resolver = contentResolver
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
val where = Expression.equalsArgs(Accounts._ID).sql
|
||||
val whereArgs = arrayOf(id.toString())
|
||||
resolver.delete(Accounts.CONTENT_URI, where, whereArgs)
|
||||
// Also delete tweets related to the account we previously
|
||||
// deleted.
|
||||
resolver.delete(Statuses.CONTENT_URI, where, whereArgs)
|
||||
resolver.delete(Mentions.CONTENT_URI, where, whereArgs)
|
||||
resolver.delete(Inbox.CONTENT_URI, where, whereArgs)
|
||||
resolver.delete(Outbox.CONTENT_URI, where, whereArgs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val context = context
|
||||
val builder = AlertDialog.Builder(context)
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
builder.setPositiveButton(android.R.string.ok, this)
|
||||
builder.setTitle(R.string.account_delete_confirm_title)
|
||||
builder.setMessage(R.string.account_delete_confirm_message)
|
||||
return builder.create()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion"
|
||||
}
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* 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.fragment
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.ContentValues
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v7.app.AlertDialog
|
||||
import com.twitter.Extractor
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_STATUS
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_NAME_FIRST
|
||||
import org.mariotaku.twidere.model.ParcelableStatus
|
||||
import org.mariotaku.twidere.model.ParcelableUserMention
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator
|
||||
import org.mariotaku.twidere.util.HtmlEscapeHelper
|
||||
import org.mariotaku.twidere.util.ParseUtils
|
||||
import org.mariotaku.twidere.util.UserColorNameManager
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||
import java.util.*
|
||||
|
||||
class AddStatusFilterDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private val extractor = Extractor()
|
||||
private var filterItems: Array<FilterItemInfo>? = null
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(context)
|
||||
filterItems = filterItemsInfo
|
||||
val entries = arrayOfNulls<String>(filterItems!!.size)
|
||||
val nameFirst = preferences.getBoolean(KEY_NAME_FIRST)
|
||||
run {
|
||||
var i = 0
|
||||
val j = entries.size
|
||||
while (i < j) {
|
||||
val info = filterItems!![i]
|
||||
when (info.type) {
|
||||
FilterItemInfo.FILTER_TYPE_USER -> {
|
||||
entries[i] = getString(R.string.user_filter_name, getName(userColorNameManager,
|
||||
info.value, nameFirst))
|
||||
}
|
||||
FilterItemInfo.FILTER_TYPE_KEYWORD -> {
|
||||
entries[i] = getString(R.string.keyword_filter_name, getName(userColorNameManager,
|
||||
info.value, nameFirst))
|
||||
}
|
||||
FilterItemInfo.FILTER_TYPE_SOURCE -> {
|
||||
entries[i] = getString(R.string.source_filter_name, getName(userColorNameManager,
|
||||
info.value, nameFirst))
|
||||
}
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
builder.setTitle(R.string.add_to_filter)
|
||||
builder.setMultiChoiceItems(entries, null, null)
|
||||
builder.setPositiveButton(android.R.string.ok) { dialog, which ->
|
||||
val alertDialog = dialog as AlertDialog
|
||||
val checkPositions = alertDialog.listView.checkedItemPositions
|
||||
|
||||
val userKeys = HashSet<UserKey>()
|
||||
val keywords = HashSet<String>()
|
||||
val sources = HashSet<String>()
|
||||
val userValues = ArrayList<ContentValues>()
|
||||
val keywordValues = ArrayList<ContentValues>()
|
||||
val sourceValues = ArrayList<ContentValues>()
|
||||
var i = 0
|
||||
val j = checkPositions.size()
|
||||
while (i < j) {
|
||||
if (!checkPositions.valueAt(i)) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
val info = filterItems!![checkPositions.keyAt(i)]
|
||||
val value = info.value
|
||||
if (value is ParcelableUserMention) {
|
||||
userKeys.add(value.key)
|
||||
userValues.add(ContentValuesCreator.createFilteredUser(value))
|
||||
} else if (value is UserItem) {
|
||||
userKeys.add(value.key)
|
||||
userValues.add(createFilteredUser(value))
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_KEYWORD) {
|
||||
val keyword = ParseUtils.parseString(value)
|
||||
keywords.add(keyword)
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Keywords.VALUE, "#" + keyword)
|
||||
keywordValues.add(values)
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_SOURCE) {
|
||||
val source = ParseUtils.parseString(value)
|
||||
sources.add(source)
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Sources.VALUE, source)
|
||||
sourceValues.add(values)
|
||||
}
|
||||
i++
|
||||
}
|
||||
val resolver = contentResolver
|
||||
ContentResolverUtils.bulkDelete(resolver, Filters.Users.CONTENT_URI, Filters.Users.USER_KEY, userKeys, null)
|
||||
ContentResolverUtils.bulkDelete(resolver, Filters.Keywords.CONTENT_URI, Filters.Keywords.VALUE, keywords, null)
|
||||
ContentResolverUtils.bulkDelete(resolver, Filters.Sources.CONTENT_URI, Filters.Sources.VALUE, sources, null)
|
||||
ContentResolverUtils.bulkInsert(resolver, Filters.Users.CONTENT_URI, userValues)
|
||||
ContentResolverUtils.bulkInsert(resolver, Filters.Keywords.CONTENT_URI, keywordValues)
|
||||
ContentResolverUtils.bulkInsert(resolver, Filters.Sources.CONTENT_URI, sourceValues)
|
||||
}
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
return builder.create()
|
||||
}
|
||||
|
||||
private val filterItemsInfo: Array<FilterItemInfo>
|
||||
get() {
|
||||
val args = arguments
|
||||
if (args == null || !args.containsKey(EXTRA_STATUS)) return emptyArray()
|
||||
val status = args.getParcelable<ParcelableStatus>(EXTRA_STATUS) ?: return emptyArray()
|
||||
val list = ArrayList<FilterItemInfo>()
|
||||
if (status.is_retweet && status.retweeted_by_user_key != null) {
|
||||
list.add(FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER,
|
||||
UserItem(status.retweeted_by_user_key!!, status.retweeted_by_user_name,
|
||||
status.retweeted_by_user_screen_name)))
|
||||
}
|
||||
if (status.is_quote && status.quoted_user_key != null) {
|
||||
list.add(FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER,
|
||||
UserItem(status.quoted_user_key!!, status.quoted_user_name,
|
||||
status.quoted_user_screen_name)))
|
||||
}
|
||||
list.add(FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, UserItem(status.user_key,
|
||||
status.user_name, status.user_screen_name)))
|
||||
val mentions = status.mentions
|
||||
if (mentions != null) {
|
||||
for (mention in mentions) {
|
||||
if (mention.key != status.user_key) {
|
||||
list.add(FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, mention))
|
||||
}
|
||||
}
|
||||
}
|
||||
val hashtags = HashSet<String>()
|
||||
hashtags.addAll(extractor.extractHashtags(status.text_plain))
|
||||
for (hashtag in hashtags) {
|
||||
list.add(FilterItemInfo(FilterItemInfo.FILTER_TYPE_KEYWORD, hashtag))
|
||||
}
|
||||
val source = HtmlEscapeHelper.toPlainText(status.source)
|
||||
list.add(FilterItemInfo(FilterItemInfo.FILTER_TYPE_SOURCE, source))
|
||||
return list.toTypedArray()
|
||||
}
|
||||
|
||||
private fun getName(manager: UserColorNameManager, value: Any, nameFirst: Boolean): String {
|
||||
if (value is ParcelableUserMention) {
|
||||
return manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
|
||||
} else if (value is UserItem) {
|
||||
return manager.getDisplayName(value.key, value.name, value.screen_name, nameFirst)
|
||||
} else
|
||||
return ParseUtils.parseString(value)
|
||||
}
|
||||
|
||||
internal data class FilterItemInfo(
|
||||
val type: Int,
|
||||
val value: Any
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
||||
internal const val FILTER_TYPE_USER = 1
|
||||
internal const val FILTER_TYPE_KEYWORD = 2
|
||||
internal const val FILTER_TYPE_SOURCE = 3
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal data class UserItem(
|
||||
val key: UserKey,
|
||||
val name: String,
|
||||
val screen_name: String
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "add_status_filter"
|
||||
|
||||
private fun createFilteredUser(item: UserItem): ContentValues {
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Users.USER_KEY, item.key.toString())
|
||||
values.put(Filters.Users.NAME, item.name)
|
||||
values.put(Filters.Users.SCREEN_NAME, item.screen_name)
|
||||
return values
|
||||
}
|
||||
|
||||
fun show(fm: FragmentManager, status: ParcelableStatus): AddStatusFilterDialogFragment {
|
||||
val args = Bundle()
|
||||
args.putParcelable(EXTRA_STATUS, status)
|
||||
val f = AddStatusFilterDialogFragment()
|
||||
f.arguments = args
|
||||
f.show(fm, FRAGMENT_TAG)
|
||||
return f
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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.fragment
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.graphics.Paint
|
||||
import android.graphics.PorterDuff.Mode
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
||||
import android.support.v4.content.CursorLoader
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v4.content.res.ResourcesCompat
|
||||
import android.text.TextUtils
|
||||
import android.view.*
|
||||
import android.widget.AbsListView
|
||||
import android.widget.AbsListView.MultiChoiceModeListener
|
||||
import android.widget.AdapterView
|
||||
import android.widget.AdapterView.OnItemClickListener
|
||||
import android.widget.ListView
|
||||
import com.afollestad.appthemeengine.ATEActivity
|
||||
import com.afollestad.appthemeengine.Config
|
||||
import com.mobeta.android.dslv.SimpleDragSortCursorAdapter
|
||||
import kotlinx.android.synthetic.main.layout_draggable_list_with_empty_view.*
|
||||
import org.mariotaku.sqliteqb.library.Columns.Column
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.sqliteqb.library.RawItemArray
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.*
|
||||
import org.mariotaku.twidere.activity.CustomTabEditorActivity
|
||||
import org.mariotaku.twidere.activity.SettingsActivity
|
||||
import org.mariotaku.twidere.model.CustomTabConfiguration
|
||||
import org.mariotaku.twidere.model.CustomTabConfiguration.CustomTabConfigurationComparator
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs
|
||||
import org.mariotaku.twidere.util.CustomTabUtils
|
||||
import org.mariotaku.twidere.util.DataStoreUtils
|
||||
import org.mariotaku.twidere.util.ThemeUtils
|
||||
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder
|
||||
import java.util.*
|
||||
|
||||
class CustomTabsFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, MultiChoiceModeListener, OnItemClickListener {
|
||||
|
||||
private var adapter: CustomTabsAdapter? = null
|
||||
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.delete -> {
|
||||
val itemIds = listView.checkedItemIds
|
||||
val where = Expression.`in`(Column(Tabs._ID), RawItemArray(itemIds))
|
||||
contentResolver.delete(Tabs.CONTENT_URI, where.sql, null)
|
||||
SettingsActivity.setShouldNotifyChange(activity)
|
||||
}
|
||||
}
|
||||
mode.finish()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
adapter = CustomTabsAdapter(context)
|
||||
listView.choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL
|
||||
listView.setMultiChoiceModeListener(this)
|
||||
listView.onItemClickListener = this
|
||||
listView.adapter = adapter
|
||||
listView.emptyView = emptyView
|
||||
listView.setDropListener { from, to ->
|
||||
adapter!!.drop(from, to)
|
||||
if (listView.choiceMode != AbsListView.CHOICE_MODE_NONE) {
|
||||
listView.moveCheckState(from, to)
|
||||
}
|
||||
saveTabPositions()
|
||||
}
|
||||
emptyText.setText(R.string.no_tab)
|
||||
emptyIcon.setImageResource(R.drawable.ic_info_tab)
|
||||
loaderManager.initLoader(0, null, this)
|
||||
setListShown(false)
|
||||
}
|
||||
|
||||
override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
|
||||
val c = adapter!!.cursor
|
||||
c.moveToPosition(adapter!!.getCursorPosition(position))
|
||||
val intent = Intent(INTENT_ACTION_EDIT_TAB)
|
||||
intent.setClass(activity, CustomTabEditorActivity::class.java)
|
||||
intent.putExtra(EXTRA_ID, c.getLong(c.getColumnIndex(Tabs._ID)))
|
||||
intent.putExtra(EXTRA_TYPE, c.getString(c.getColumnIndex(Tabs.TYPE)))
|
||||
intent.putExtra(EXTRA_NAME, c.getString(c.getColumnIndex(Tabs.NAME)))
|
||||
intent.putExtra(EXTRA_ICON, c.getString(c.getColumnIndex(Tabs.ICON)))
|
||||
intent.putExtra(EXTRA_EXTRAS, c.getString(c.getColumnIndex(Tabs.EXTRAS)))
|
||||
startActivityForResult(intent, REQUEST_EDIT_TAB)
|
||||
}
|
||||
|
||||
private fun setListShown(shown: Boolean) {
|
||||
listContainer.visibility = if (shown) View.VISIBLE else View.GONE
|
||||
progressContainer.visibility = if (shown) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when (requestCode) {
|
||||
REQUEST_ADD_TAB -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
val values = ContentValues()
|
||||
values.put(Tabs.NAME, data!!.getStringExtra(EXTRA_NAME))
|
||||
values.put(Tabs.ICON, data.getStringExtra(EXTRA_ICON))
|
||||
values.put(Tabs.TYPE, data.getStringExtra(EXTRA_TYPE))
|
||||
values.put(Tabs.ARGUMENTS, data.getStringExtra(EXTRA_ARGUMENTS))
|
||||
values.put(Tabs.EXTRAS, data.getStringExtra(EXTRA_EXTRAS))
|
||||
values.put(Tabs.POSITION, adapter!!.count)
|
||||
contentResolver.insert(Tabs.CONTENT_URI, values)
|
||||
SettingsActivity.setShouldNotifyChange(activity)
|
||||
}
|
||||
}
|
||||
REQUEST_EDIT_TAB -> {
|
||||
if (resultCode == Activity.RESULT_OK && data!!.hasExtra(EXTRA_ID)) {
|
||||
val values = ContentValues()
|
||||
values.put(Tabs.NAME, data.getStringExtra(EXTRA_NAME))
|
||||
values.put(Tabs.ICON, data.getStringExtra(EXTRA_ICON))
|
||||
values.put(Tabs.EXTRAS, data.getStringExtra(EXTRA_EXTRAS))
|
||||
val where = Expression.equals(Tabs._ID, data.getLongExtra(EXTRA_ID, -1)).sql
|
||||
contentResolver.update(Tabs.CONTENT_URI, values, where, null)
|
||||
SettingsActivity.setShouldNotifyChange(activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
mode.menuInflater.inflate(R.menu.action_multi_select_items, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor?> {
|
||||
return CursorLoader(activity, Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, Tabs.DEFAULT_SORT_ORDER)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
|
||||
inflater!!.inflate(R.menu.menu_custom_tabs, menu)
|
||||
val res = resources
|
||||
val activity = activity
|
||||
val accountIds = DataStoreUtils.getAccountKeys(activity)
|
||||
val itemAdd = menu!!.findItem(R.id.add_submenu)
|
||||
if (itemAdd != null && itemAdd.hasSubMenu()) {
|
||||
val subMenu = itemAdd.subMenu
|
||||
subMenu.clear()
|
||||
val map = CustomTabUtils.getConfigurationMap()
|
||||
val tabs = ArrayList(
|
||||
map.entries)
|
||||
Collections.sort(tabs, CustomTabConfigurationComparator.SINGLETON)
|
||||
for ((type, conf) in tabs) {
|
||||
|
||||
val accountIdRequired = conf.accountRequirement == CustomTabConfiguration.ACCOUNT_REQUIRED
|
||||
|
||||
val intent = Intent(INTENT_ACTION_ADD_TAB)
|
||||
intent.setClass(activity, CustomTabEditorActivity::class.java)
|
||||
intent.putExtra(EXTRA_TYPE, type)
|
||||
|
||||
val subItem = subMenu.add(conf.defaultTitle)
|
||||
val disabledByNoAccount = accountIdRequired && accountIds.size == 0
|
||||
val disabledByDuplicateTab = conf.isSingleTab && CustomTabUtils.isTabAdded(activity, type)
|
||||
val shouldDisable = disabledByDuplicateTab || disabledByNoAccount
|
||||
subItem.isVisible = !shouldDisable
|
||||
subItem.isEnabled = !shouldDisable
|
||||
val icon = ResourcesCompat.getDrawable(res, conf.defaultIcon, null)
|
||||
if (icon != null && activity is ATEActivity) {
|
||||
icon.mutate().setColorFilter(Config.textColorPrimary(activity,
|
||||
activity.ateKey), Mode.SRC_ATOP)
|
||||
}
|
||||
subItem.icon = icon
|
||||
subItem.intent = intent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.layout_draggable_list_with_empty_view, container, false)
|
||||
}
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode) {
|
||||
|
||||
}
|
||||
|
||||
override fun onItemCheckedStateChanged(mode: ActionMode, position: Int, id: Long,
|
||||
checked: Boolean) {
|
||||
updateTitle(mode)
|
||||
}
|
||||
|
||||
|
||||
override fun onLoaderReset(loader: Loader<Cursor?>) {
|
||||
adapter!!.changeCursor(null)
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<Cursor?>, cursor: Cursor?) {
|
||||
adapter!!.changeCursor(cursor)
|
||||
setListShown(true)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||
when (item!!.itemId) {
|
||||
else -> {
|
||||
val intent = item.intent ?: return false
|
||||
startActivityForResult(intent, REQUEST_ADD_TAB)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
updateTitle(mode)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
private fun saveTabPositions() {
|
||||
val positions = adapter!!.cursorPositions
|
||||
val c = adapter!!.cursor
|
||||
if (positions != null && c != null && !c.isClosed) {
|
||||
val idIdx = c.getColumnIndex(Tabs._ID)
|
||||
var i = 0
|
||||
val j = positions.size
|
||||
while (i < j) {
|
||||
c.moveToPosition(positions[i])
|
||||
val id = c.getLong(idIdx)
|
||||
val values = ContentValues()
|
||||
values.put(Tabs.POSITION, i)
|
||||
val where = Expression.equals(Tabs._ID, id).sql
|
||||
contentResolver.update(Tabs.CONTENT_URI, values, where, null)
|
||||
i++
|
||||
}
|
||||
}
|
||||
SettingsActivity.setShouldNotifyChange(activity)
|
||||
}
|
||||
|
||||
private fun updateTitle(mode: ActionMode?) {
|
||||
if (listView == null || mode == null || activity == null) return
|
||||
val count = listView.checkedItemCount
|
||||
mode.title = resources.getQuantityString(R.plurals.Nitems_selected, count, count)
|
||||
}
|
||||
|
||||
class CustomTabsAdapter(context: Context) : SimpleDragSortCursorAdapter(context, R.layout.list_item_custom_tab, null, arrayOfNulls<String>(0), IntArray(0), 0) {
|
||||
|
||||
private val mIconColor: Int
|
||||
private var indices: CursorIndices? = null
|
||||
|
||||
init {
|
||||
mIconColor = ThemeUtils.getThemeForegroundColor(context)
|
||||
}
|
||||
|
||||
override fun bindView(view: View, context: Context?, cursor: Cursor) {
|
||||
super.bindView(view, context, cursor)
|
||||
val holder = view.tag as TwoLineWithIconViewHolder
|
||||
val indices = indices!!
|
||||
val type = cursor.getString(indices.type)
|
||||
val name = cursor.getString(indices.name)
|
||||
val iconKey = cursor.getString(indices.icon)
|
||||
if (CustomTabUtils.isTabTypeValid(type)) {
|
||||
val typeName = CustomTabUtils.getTabTypeName(context, type)
|
||||
holder.text1.text = if (TextUtils.isEmpty(name)) typeName else name
|
||||
holder.text1.paintFlags = holder.text1.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
||||
holder.text2.visibility = View.VISIBLE
|
||||
holder.text2.text = typeName
|
||||
} else {
|
||||
holder.text1.text = name
|
||||
holder.text1.paintFlags = holder.text1.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
||||
holder.text2.setText(R.string.invalid_tab)
|
||||
}
|
||||
val icon = CustomTabUtils.getTabIconDrawable(context, CustomTabUtils.getTabIconObject(iconKey))
|
||||
holder.icon.visibility = View.VISIBLE
|
||||
if (icon != null) {
|
||||
holder.icon.setImageDrawable(icon)
|
||||
} else {
|
||||
holder.icon.setImageResource(R.drawable.ic_action_list)
|
||||
}
|
||||
holder.icon.setColorFilter(mIconColor, Mode.SRC_ATOP)
|
||||
}
|
||||
|
||||
override fun changeCursor(cursor: Cursor?) {
|
||||
if (cursor != null) {
|
||||
indices = CursorIndices(cursor)
|
||||
}
|
||||
super.changeCursor(cursor)
|
||||
}
|
||||
|
||||
override fun newView(context: Context?, cursor: Cursor?, parent: ViewGroup): View {
|
||||
val view = super.newView(context, cursor, parent)
|
||||
val tag = view.tag
|
||||
if (tag !is TwoLineWithIconViewHolder) {
|
||||
val holder = TwoLineWithIconViewHolder(view)
|
||||
view.tag = holder
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
internal class CursorIndices(cursor: Cursor) {
|
||||
val _id: Int
|
||||
val name: Int
|
||||
val icon: Int
|
||||
val type: Int
|
||||
val arguments: Int
|
||||
|
||||
init {
|
||||
_id = cursor.getColumnIndex(Tabs._ID)
|
||||
icon = cursor.getColumnIndex(Tabs.ICON)
|
||||
name = cursor.getColumnIndex(Tabs.NAME)
|
||||
type = cursor.getColumnIndex(Tabs.TYPE)
|
||||
arguments = cursor.getColumnIndex(Tabs.ARGUMENTS)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.fragment
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v7.app.AlertDialog
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_STATUS
|
||||
import org.mariotaku.twidere.model.ParcelableStatus
|
||||
|
||||
class DestroyStatusDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
|
||||
|
||||
override fun onClick(dialog: DialogInterface, which: Int) {
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
val status = status ?: return
|
||||
twitterWrapper.destroyStatusAsync(status.account_key, status.id)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val context = activity
|
||||
val builder = AlertDialog.Builder(context)
|
||||
builder.setTitle(R.string.destroy_status)
|
||||
builder.setMessage(R.string.destroy_status_confirm_message)
|
||||
builder.setPositiveButton(android.R.string.ok, this)
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
return builder.create()
|
||||
}
|
||||
|
||||
private val status: ParcelableStatus?
|
||||
get() {
|
||||
val args = arguments
|
||||
if (!args.containsKey(EXTRA_STATUS)) return null
|
||||
return args.getParcelable<ParcelableStatus>(EXTRA_STATUS)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val FRAGMENT_TAG = "destroy_status"
|
||||
|
||||
fun show(fm: FragmentManager, status: ParcelableStatus): DestroyStatusDialogFragment {
|
||||
val args = Bundle()
|
||||
args.putParcelable(EXTRA_STATUS, status)
|
||||
val f = DestroyStatusDialogFragment()
|
||||
f.arguments = args
|
||||
f.show(fm, FRAGMENT_TAG)
|
||||
return f
|
||||
}
|
||||
}
|
||||
}
|
@ -35,9 +35,9 @@ import android.support.v4.content.CursorLoader
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v4.view.ViewCompat
|
||||
import android.support.v7.app.ActionBar
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.FixedLinearLayoutManager
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.PopupMenu
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.text.Editable
|
||||
import android.text.TextUtils
|
||||
@ -50,7 +50,7 @@ import android.widget.AdapterView.OnItemSelectedListener
|
||||
import android.widget.Toast
|
||||
import com.squareup.otto.Subscribe
|
||||
import kotlinx.android.synthetic.main.fragment_messages_conversation.*
|
||||
import kotlinx.android.synthetic.main.layout_actionbar_message_user_picker.*
|
||||
import kotlinx.android.synthetic.main.layout_actionbar_message_user_picker.view.*
|
||||
import me.uucky.colorpicker.internal.EffectViewHelper
|
||||
import org.mariotaku.sqliteqb.library.Columns.Column
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
@ -85,15 +85,15 @@ import org.mariotaku.twidere.view.ExtendedRecyclerView
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, OnClickListener, OnItemSelectedListener, PopupMenu.OnMenuItemClickListener, KeyboardShortcutCallback, TakeAllKeyboardShortcut {
|
||||
|
||||
class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, OnClickListener,
|
||||
OnItemSelectedListener, KeyboardShortcutCallback, TakeAllKeyboardShortcut {
|
||||
|
||||
// Callbacks and listeners
|
||||
private val searchLoadersCallback = object : LoaderCallbacks<List<ParcelableUser>> {
|
||||
override fun onCreateLoader(id: Int, args: Bundle): Loader<List<ParcelableUser>> {
|
||||
usersSearchList!!.visibility = View.GONE
|
||||
usersSearchEmpty!!.visibility = View.GONE
|
||||
usersSearchProgress!!.visibility = View.VISIBLE
|
||||
usersSearchList.visibility = View.GONE
|
||||
usersSearchEmpty.visibility = View.GONE
|
||||
usersSearchProgress.visibility = View.VISIBLE
|
||||
val accountKey = args.getParcelable<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
val query = args.getString(EXTRA_QUERY)
|
||||
val fromCache = args.getBoolean(EXTRA_FROM_CACHE)
|
||||
@ -103,10 +103,10 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<ParcelableUser>>, data: List<ParcelableUser>?) {
|
||||
usersSearchList!!.visibility = View.VISIBLE
|
||||
usersSearchProgress!!.visibility = View.GONE
|
||||
usersSearchEmpty!!.visibility = if (data == null || data.isEmpty()) View.GONE else View.VISIBLE
|
||||
mUsersSearchAdapter!!.setData(data, true)
|
||||
usersSearchList.visibility = View.VISIBLE
|
||||
usersSearchProgress.visibility = View.GONE
|
||||
usersSearchEmpty.visibility = if (data == null || data.isEmpty()) View.GONE else View.VISIBLE
|
||||
usersSearchAdapter!!.setData(data, true)
|
||||
updateEmptyText()
|
||||
}
|
||||
|
||||
@ -121,12 +121,11 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
|
||||
// Adapters
|
||||
private var adapter: MessageConversationAdapter? = null
|
||||
private var mUsersSearchAdapter: SimpleParcelableUsersAdapter? = null
|
||||
private var usersSearchAdapter: SimpleParcelableUsersAdapter? = null
|
||||
|
||||
// Data fields
|
||||
private var searchUsersLoaderInitialized: Boolean = false
|
||||
private var navigateBackPressed: Boolean = false
|
||||
private val selectedDirectMessage: ParcelableDirectMessage? = null
|
||||
private var loaderInitialized: Boolean = false
|
||||
private var imageUri: String? = null
|
||||
private var account: ParcelableCredentials? = null
|
||||
@ -136,6 +135,9 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
|
||||
private val backTimeoutRunnable = Runnable { navigateBackPressed = false }
|
||||
|
||||
private val actionBarCustomView: View
|
||||
get() = (activity as AppCompatActivity).supportActionBar!!.customView
|
||||
|
||||
@Subscribe
|
||||
fun notifyTaskStateChanged(event: TaskStateChangedEvent) {
|
||||
updateRefreshState()
|
||||
@ -163,10 +165,8 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
val activity = activity as BaseActivity
|
||||
messageDrafts = activity.getSharedPreferences(MESSAGE_DRAFTS_PREFERENCES_NAME, Context.MODE_PRIVATE)
|
||||
|
||||
val view = view!!
|
||||
val viewContext = view.context
|
||||
setHasOptionsMenu(true)
|
||||
val actionBar = activity.supportActionBar ?: throw NullPointerException()
|
||||
val actionBar = activity.supportActionBar!!
|
||||
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
|
||||
ActionBar.DISPLAY_SHOW_TITLE or ActionBar.DISPLAY_SHOW_CUSTOM)
|
||||
actionBar.setCustomView(R.layout.layout_actionbar_message_user_picker)
|
||||
@ -175,11 +175,11 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
actionBar.themedContext, R.layout.spinner_item_account_icon)
|
||||
accountsSpinnerAdapter.setDropDownViewResource(R.layout.list_item_user)
|
||||
accountsSpinnerAdapter.addAll(accounts)
|
||||
accountSpinner.adapter = accountsSpinnerAdapter
|
||||
accountSpinner.onItemSelectedListener = this
|
||||
queryButton.setOnClickListener(this)
|
||||
actionBarCustomView.accountSpinner.adapter = accountsSpinnerAdapter
|
||||
actionBarCustomView.accountSpinner.onItemSelectedListener = this
|
||||
actionBarCustomView.queryButton.setOnClickListener(this)
|
||||
adapter = MessageConversationAdapter(activity)
|
||||
val layoutManager = FixedLinearLayoutManager(viewContext)
|
||||
val layoutManager = FixedLinearLayoutManager(context)
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
layoutManager.stackFromEnd = true
|
||||
recyclerView.layoutManager = layoutManager
|
||||
@ -197,24 +197,24 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
scrollListener = PanelShowHideListener(effectHelper)
|
||||
|
||||
inputPanelShadowCompat!!.visibility = if (useOutline) View.GONE else View.VISIBLE
|
||||
inputPanelShadowCompat.visibility = if (useOutline) View.GONE else View.VISIBLE
|
||||
ViewCompat.setAlpha(inputPanelShadowCompat, 0f)
|
||||
|
||||
mUsersSearchAdapter = SimpleParcelableUsersAdapter(activity)
|
||||
usersSearchList!!.adapter = mUsersSearchAdapter
|
||||
usersSearchList!!.emptyView = usersSearchEmpty
|
||||
usersSearchList!!.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
|
||||
val account = accountSpinner.selectedItem as ParcelableCredentials
|
||||
showConversation(account, mUsersSearchAdapter!!.getItem(position))
|
||||
usersSearchAdapter = SimpleParcelableUsersAdapter(activity)
|
||||
usersSearchList.adapter = usersSearchAdapter
|
||||
usersSearchList.emptyView = usersSearchEmpty
|
||||
usersSearchList.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
|
||||
val account = actionBarCustomView.accountSpinner.selectedItem as ParcelableCredentials
|
||||
showConversation(account, usersSearchAdapter!!.getItem(position))
|
||||
updateRecipientInfo()
|
||||
}
|
||||
|
||||
setupEditQuery()
|
||||
setupEditText()
|
||||
|
||||
send!!.setOnClickListener(this)
|
||||
addImage!!.setOnClickListener(this)
|
||||
send!!.isEnabled = false
|
||||
sendMessage.setOnClickListener(this)
|
||||
addImage.setOnClickListener(this)
|
||||
sendMessage.isEnabled = false
|
||||
if (savedInstanceState != null) {
|
||||
val account = savedInstanceState.getParcelable<ParcelableCredentials>(EXTRA_ACCOUNT)
|
||||
val recipient = savedInstanceState.getParcelable<ParcelableUser>(EXTRA_USER)
|
||||
@ -237,7 +237,7 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
val accountPos = accountsSpinnerAdapter.findPositionByKey(accountKey)
|
||||
if (accountPos >= 0) {
|
||||
accountSpinner.setSelection(accountPos)
|
||||
actionBarCustomView.accountSpinner.setSelection(accountPos)
|
||||
}
|
||||
val userId = args.getString(EXTRA_RECIPIENT_ID)
|
||||
if (accountPos >= 0) {
|
||||
@ -263,11 +263,11 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
editText.setSelection(editText.length())
|
||||
val isValid = account != null && recipient != null
|
||||
conversationContainer!!.visibility = if (isValid) View.VISIBLE else View.GONE
|
||||
recipientSelectorContainer!!.visibility = if (isValid) View.GONE else View.VISIBLE
|
||||
conversationContainer.visibility = if (isValid) View.VISIBLE else View.GONE
|
||||
recipientSelectorContainer.visibility = if (isValid) View.GONE else View.VISIBLE
|
||||
|
||||
usersSearchList!!.visibility = View.GONE
|
||||
usersSearchProgress!!.visibility = View.GONE
|
||||
usersSearchList.visibility = View.GONE
|
||||
usersSearchProgress.visibility = View.GONE
|
||||
|
||||
registerForContextMenu(recyclerView)
|
||||
|
||||
@ -360,23 +360,23 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.send -> {
|
||||
when (view) {
|
||||
sendMessage -> {
|
||||
sendDirectMessage()
|
||||
}
|
||||
R.id.addImage -> {
|
||||
addImage -> {
|
||||
val intent = ThemedImagePickerActivity.withThemed(activity).build()
|
||||
startActivityForResult(intent, REQUEST_PICK_IMAGE)
|
||||
}
|
||||
R.id.queryButton -> {
|
||||
val account = accountSpinner.selectedItem as ParcelableCredentials
|
||||
searchUsers(account.account_key, ParseUtils.parseString(editUserQuery!!.text), false)
|
||||
actionBarCustomView.queryButton -> {
|
||||
val account = actionBarCustomView.accountSpinner.selectedItem as ParcelableCredentials
|
||||
searchUsers(account.account_key, ParseUtils.parseString(actionBarCustomView.editUserQuery.text), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemSelected(parent: AdapterView<*>, view: View, pos: Int, id: Long) {
|
||||
val account = accountSpinner.selectedItem as ParcelableCredentials?
|
||||
val account = actionBarCustomView.accountSpinner.selectedItem as ParcelableCredentials?
|
||||
if (account != null) {
|
||||
this.account = account
|
||||
updateRecipientInfo()
|
||||
@ -392,24 +392,6 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
adapter!!.setCursor(null)
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
val message = selectedDirectMessage
|
||||
if (message != null) {
|
||||
when (item.itemId) {
|
||||
R.id.delete -> {
|
||||
twitterWrapper.destroyDirectMessageAsync(message.account_key, message.id)
|
||||
}
|
||||
R.id.copy -> {
|
||||
if (ClipboardUtils.setText(activity, message.text_plain)) {
|
||||
Utils.showOkMessage(activity, R.string.text_copied, false)
|
||||
}
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<Cursor?>, cursor: Cursor?) {
|
||||
adapter!!.setCursor(cursor)
|
||||
}
|
||||
@ -450,7 +432,7 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
val action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState)
|
||||
if (ACTION_NAVIGATION_BACK == action) {
|
||||
val showingConversation = isShowingConversation
|
||||
val editText = if (showingConversation) editText else editUserQuery
|
||||
val editText = if (showingConversation) editText else actionBarCustomView.editUserQuery
|
||||
val textChanged = if (showingConversation) textChanged else queryTextChanged
|
||||
if (editText.length() == 0 && !textChanged) {
|
||||
val activity = activity
|
||||
@ -505,9 +487,9 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
private fun updateAccount() {
|
||||
if (account == null) return
|
||||
if (Utils.isOfficialCredentials(context, account!!)) {
|
||||
addImage!!.visibility = View.VISIBLE
|
||||
addImage.visibility = View.VISIBLE
|
||||
} else {
|
||||
addImage!!.visibility = View.GONE
|
||||
addImage.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,7 +558,7 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
|
||||
private fun setupEditQuery() {
|
||||
val queryEnterHandler = EditTextEnterHandler.attach(editUserQuery!!, object : EnterListener {
|
||||
val queryEnterHandler = EditTextEnterHandler.attach(actionBarCustomView.editUserQuery, object : EnterListener {
|
||||
override fun shouldCallListener(): Boolean {
|
||||
val activity = activity
|
||||
if (activity !is BaseActivity) return false
|
||||
@ -587,9 +569,9 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
val activity = activity
|
||||
if (activity !is BaseActivity) return false
|
||||
if (activity.keyMetaState != 0) return false
|
||||
val account = accountSpinner.selectedItem as ParcelableCredentials ?: return false
|
||||
val account = actionBarCustomView.accountSpinner.selectedItem as ParcelableCredentials ?: return false
|
||||
editText.setAccountKey(account.account_key)
|
||||
searchUsers(account.account_key, ParseUtils.parseString(editUserQuery!!.text), false)
|
||||
searchUsers(account.account_key, ParseUtils.parseString(actionBarCustomView.editUserQuery.text), false)
|
||||
return true
|
||||
}
|
||||
}, true)
|
||||
@ -602,12 +584,12 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
val account = (accountSpinner.selectedItem ?: return) as ParcelableCredentials
|
||||
val account = (actionBarCustomView.accountSpinner.selectedItem ?: return) as ParcelableCredentials
|
||||
editText.setAccountKey(account.account_key)
|
||||
searchUsers(account.account_key, ParseUtils.parseString(s), true)
|
||||
}
|
||||
})
|
||||
editUserQuery!!.addTextChangedListener(object : TextWatcher {
|
||||
actionBarCustomView.editUserQuery.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
||||
|
||||
}
|
||||
@ -645,8 +627,8 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
if (send == null || s == null) return
|
||||
send!!.isEnabled = validator.isValidDirectMessage(s.toString())
|
||||
if (s == null) return
|
||||
sendMessage.isEnabled = validator.isValidDirectMessage(s.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -659,7 +641,7 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
}
|
||||
|
||||
private fun updateAddImageButton() {
|
||||
addImage!!.isActivated = imageUri != null
|
||||
addImage.isActivated = imageUri != null
|
||||
}
|
||||
|
||||
// @Override
|
||||
@ -670,7 +652,7 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
|
||||
// }
|
||||
|
||||
private fun updateEmptyText() {
|
||||
val noQuery = editUserQuery!!.length() <= 0
|
||||
val noQuery = actionBarCustomView.editUserQuery!!.length() <= 0
|
||||
if (noQuery) {
|
||||
usersSearchEmptyText!!.setText(R.string.type_name_to_search)
|
||||
} else {
|
||||
|
@ -0,0 +1,8 @@
|
||||
package org.mariotaku.twidere.fragment
|
||||
|
||||
import android.support.v4.app.Fragment
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/3/28.
|
||||
*/
|
||||
class MessagesEntriesFragment : Fragment()
|
@ -80,7 +80,7 @@
|
||||
android:visibility="gone"/>
|
||||
|
||||
<org.mariotaku.twidere.view.IconActionView
|
||||
android:id="@+id/send"
|
||||
android:id="@+id/sendMessage"
|
||||
android:layout_width="@dimen/element_size_normal"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
android:layout_alignParentEnd="true"
|
||||
@ -99,9 +99,9 @@
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:layout_gravity="end"
|
||||
android:layout_toEndOf="@+id/addImage"
|
||||
android:layout_toLeftOf="@+id/send"
|
||||
android:layout_toLeftOf="@+id/sendMessage"
|
||||
android:layout_toRightOf="@+id/addImage"
|
||||
android:layout_toStartOf="@+id/send"
|
||||
android:layout_toStartOf="@+id/sendMessage"
|
||||
app:bubbleColor="?messageBubbleColor"
|
||||
app:caretHeight="8dp"
|
||||
app:caretPosition="topEnd"
|
||||
|
@ -26,12 +26,12 @@
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/list_container"
|
||||
android:id="@+id/listContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.mobeta.android.dslv.DragSortListView
|
||||
android:id="@android:id/list"
|
||||
android:id="@+id/listView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:collapsed_height="2dp"
|
||||
@ -50,7 +50,7 @@
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@android:id/empty"
|
||||
android:id="@+id/emptyView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
@ -58,13 +58,13 @@
|
||||
tools:visibility="visible">
|
||||
|
||||
<org.mariotaku.twidere.view.IconActionView
|
||||
android:id="@+id/empty_icon"
|
||||
android:id="@+id/emptyIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:color="?android:textColorSecondary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_text"
|
||||
android:id="@+id/emptyText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
@ -75,12 +75,12 @@
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/progress_container"
|
||||
android:id="@+id/progressContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@android:id/progress"
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user