mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-06 03:23:21 +01:00
copy link now work
fixed user auto completion
This commit is contained in:
parent
8fc291fda5
commit
8d6c2629a1
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package android.support.v7.internal.view;
|
||||
|
||||
import android.support.v7.view.ActionMode;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/4.
|
||||
*/
|
||||
public class SupportActionModeWrapperTrojan {
|
||||
|
||||
public static ActionMode getWrappedObject(SupportActionModeWrapper wrapper) {
|
||||
return wrapper.mWrappedObject;
|
||||
}
|
||||
|
||||
}
|
@ -34,6 +34,7 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
||||
@ -65,6 +66,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.getDefaultAccountId;
|
||||
|
||||
@ -250,7 +252,8 @@ public class FiltersActivity extends BaseActionBarActivity implements TabListene
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final FragmentActivity activity = getActivity();
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(activity);
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
buildDialog(builder);
|
||||
final View view = LayoutInflater.from(wrapped).inflate(R.layout.auto_complete_textview, null);
|
||||
@ -260,9 +263,11 @@ public class FiltersActivity extends BaseActionBarActivity implements TabListene
|
||||
final int auto_complete_type = args != null ? args.getInt(EXTRA_AUTO_COMPLETE_TYPE, 0) : 0;
|
||||
if (auto_complete_type != 0) {
|
||||
if (auto_complete_type == AUTO_COMPLETE_TYPE_SOURCES) {
|
||||
mUserAutoCompleteAdapter = new SourceAutoCompleteAdapter(getActivity());
|
||||
mUserAutoCompleteAdapter = new SourceAutoCompleteAdapter(activity);
|
||||
} else {
|
||||
mUserAutoCompleteAdapter = new UserHashtagAutoCompleteAdapter(getActivity());
|
||||
final UserHashtagAutoCompleteAdapter adapter = new UserHashtagAutoCompleteAdapter(activity);
|
||||
adapter.setAccountId(Utils.getDefaultAccountId(activity));
|
||||
mUserAutoCompleteAdapter = adapter;
|
||||
}
|
||||
mEditText.setAdapter(mUserAutoCompleteAdapter);
|
||||
mEditText.setThreshold(1);
|
||||
|
@ -78,7 +78,6 @@ import android.view.View.OnClickListener;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.EditText;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@ -119,6 +118,7 @@ import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.ActionIconView;
|
||||
import org.mariotaku.twidere.view.BadgeView;
|
||||
import org.mariotaku.twidere.view.ShapedImageView;
|
||||
import org.mariotaku.twidere.view.StatusComposeEditText;
|
||||
import org.mariotaku.twidere.view.StatusTextCountView;
|
||||
|
||||
import java.io.File;
|
||||
@ -173,7 +173,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
private AsyncTask<Void, Void, ?> mTask;
|
||||
private GridView mMediaPreviewGrid;
|
||||
private ActionMenuView mMenuBar;
|
||||
private EditText mEditText;
|
||||
private StatusComposeEditText mEditText;
|
||||
private View mSendView;
|
||||
private StatusTextCountView mSendTextCountView;
|
||||
private RecyclerView mAccountSelector;
|
||||
@ -577,7 +577,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
mEditText = (EditText) findViewById(R.id.edit_text);
|
||||
mEditText = (StatusComposeEditText) findViewById(R.id.edit_text);
|
||||
mMediaPreviewGrid = (GridView) findViewById(R.id.media_thumbnail_preview);
|
||||
mMenuBar = (ActionMenuView) findViewById(R.id.menu_bar);
|
||||
mSendView = findViewById(R.id.send);
|
||||
@ -1316,7 +1316,9 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
}
|
||||
|
||||
private void notifyAccountSelectionChanged() {
|
||||
setSelectedAccounts(mAccountsAdapter.getSelectedAccounts());
|
||||
final ParcelableAccount[] accounts = mAccountsAdapter.getSelectedAccounts();
|
||||
setSelectedAccounts(accounts);
|
||||
mEditText.setAccountId(accounts.length > 0 ? accounts[0].account_id : Utils.getDefaultAccountId(this));
|
||||
// mAccountActionProvider.setSelectedAccounts(mAccountsAdapter.getSelectedAccounts());
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.mariotaku.twidere.activity.support;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
@ -224,6 +225,7 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("AppCompatMethod")
|
||||
private void setActionBarBackground(ActionBar actionBar, int linkId, Uri data) {
|
||||
switch (linkId) {
|
||||
case LINK_ID_USER: {
|
||||
@ -233,11 +235,15 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
|
||||
case LINK_ID_USER_LISTS: {
|
||||
ThemeUtils.applyActionBarBackground(actionBar, this, getCurrentThemeResourceId(),
|
||||
getCurrentThemeColor(), false);
|
||||
ThemeUtils.applyActionBarBackground(getActionBar(), this, getCurrentThemeResourceId(),
|
||||
getCurrentThemeColor(), true);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ThemeUtils.applyActionBarBackground(actionBar, this, getCurrentThemeResourceId(),
|
||||
getCurrentThemeColor(), true);
|
||||
ThemeUtils.applyActionBarBackground(getActionBar(), this, getCurrentThemeResourceId(),
|
||||
getCurrentThemeColor(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,9 @@ public class UserListSelectorActivity extends BaseSupportDialogActivity implemen
|
||||
getUserLists(mScreenName);
|
||||
}
|
||||
}
|
||||
mEditScreenName.setAdapter(new UserHashtagAutoCompleteAdapter(this));
|
||||
final UserHashtagAutoCompleteAdapter adapter = new UserHashtagAutoCompleteAdapter(this);
|
||||
adapter.setAccountId(getAccountId());
|
||||
mEditScreenName.setAdapter(adapter);
|
||||
mEditScreenName.setText(mScreenName);
|
||||
mUserListsListView.setAdapter(mUserListsAdapter = new SimpleParcelableUserListsAdapter(this));
|
||||
mUsersListView.setAdapter(mUsersAdapter = new SimpleParcelableUsersAdapter(this));
|
||||
|
@ -27,7 +27,7 @@ import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.support.DirectMessagesConversationFragment;
|
||||
import org.mariotaku.twidere.fragment.support.MessagesConversationFragment;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
|
||||
@ -48,8 +48,8 @@ public class AccountsSpinnerAdapter extends ArrayAdapter<ParcelableAccount> {
|
||||
super(context, itemViewResource);
|
||||
mContext = context;
|
||||
mImageLoader = TwidereApplication.getInstance(context).getMediaLoaderWrapper();
|
||||
mDisplayProfileImage = context.getSharedPreferences(DirectMessagesConversationFragment.SHARED_PREFERENCES_NAME,
|
||||
Context.MODE_PRIVATE).getBoolean(DirectMessagesConversationFragment.KEY_DISPLAY_PROFILE_IMAGE, true);
|
||||
mDisplayProfileImage = context.getSharedPreferences(MessagesConversationFragment.SHARED_PREFERENCES_NAME,
|
||||
Context.MODE_PRIVATE).getBoolean(MessagesConversationFragment.KEY_DISPLAY_PROFILE_IMAGE, true);
|
||||
}
|
||||
|
||||
public AccountsSpinnerAdapter(final Context context, final Collection<ParcelableAccount> accounts) {
|
||||
|
@ -25,6 +25,7 @@ import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.widget.SimpleCursorAdapter;
|
||||
import android.view.View;
|
||||
@ -72,6 +73,7 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen
|
||||
|
||||
private int mProfileImageUrlIdx, mNameIdx, mScreenNameIdx, mUserIdIdx;
|
||||
private char mToken = '@';
|
||||
private long mAccountId;
|
||||
|
||||
public UserHashtagAutoCompleteAdapter(final Context context) {
|
||||
this(context, null);
|
||||
@ -172,18 +174,28 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen
|
||||
selection = null;
|
||||
selectionArgs = null;
|
||||
}
|
||||
final OrderBy orderBy = new OrderBy(CachedUsers.SCREEN_NAME, CachedUsers.NAME);
|
||||
return mResolver.query(CachedUsers.CONTENT_URI, CachedUsers.BASIC_COLUMNS,
|
||||
selection != null ? selection.getSQL() : null, selectionArgs, orderBy.getSQL());
|
||||
final OrderBy orderBy = new OrderBy(new String[]{CachedUsers.LAST_SEEN, "score", CachedUsers.SCREEN_NAME,
|
||||
CachedUsers.NAME}, new boolean[]{false, false, true, true});
|
||||
final Cursor cursor = mResolver.query(Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, String.valueOf(mAccountId)),
|
||||
CachedUsers.BASIC_COLUMNS, selection != null ? selection.getSQL() : null, selectionArgs, orderBy.getSQL());
|
||||
if (Utils.isDebugBuild() && cursor == null) throw new NullPointerException();
|
||||
return cursor;
|
||||
} else {
|
||||
final String selection = constraintEscaped != null ? CachedHashtags.NAME + " LIKE ?||'%' ESCAPE '^'"
|
||||
: null;
|
||||
final String[] selectionArgs = constraintEscaped != null ? new String[]{constraintEscaped} : null;
|
||||
return mDatabase.query(true, CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, selection, selectionArgs,
|
||||
final Cursor cursor = mDatabase.query(true, CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, selection, selectionArgs,
|
||||
null, null, CachedHashtags.NAME, null);
|
||||
if (Utils.isDebugBuild() && cursor == null) throw new NullPointerException();
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
mAccountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor swapCursor(final Cursor cursor) {
|
||||
if (cursor != null) {
|
||||
|
@ -24,6 +24,7 @@ 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.text.InputFilter;
|
||||
import android.view.LayoutInflater;
|
||||
@ -37,62 +38,65 @@ import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
||||
public class AddUserListMemberDialogFragment extends BaseSupportDialogFragment implements
|
||||
DialogInterface.OnClickListener {
|
||||
DialogInterface.OnClickListener {
|
||||
|
||||
public static final String FRAGMENT_TAG = "add_user_list_member";
|
||||
private AutoCompleteTextView mEditText;
|
||||
private UserHashtagAutoCompleteAdapter mUserAutoCompleteAdapter;
|
||||
public static final String FRAGMENT_TAG = "add_user_list_member";
|
||||
private AutoCompleteTextView mEditText;
|
||||
private UserHashtagAutoCompleteAdapter mUserAutoCompleteAdapter;
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null || !args.containsKey(EXTRA_ACCOUNT_ID) || !args.containsKey(EXTRA_LIST_ID)) return;
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
final String mText = ParseUtils.parseString(mEditText.getText());
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
if (mText == null || mText.length() <= 0 || twitter == null) return;
|
||||
// twitter.addUserListMembersAsync(args.getLong(EXTRA_ACCOUNT_ID),
|
||||
// args.getInt(EXTRA_LIST_ID), mText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null || !args.containsKey(EXTRA_ACCOUNT_ID) || !args.containsKey(EXTRA_LIST_ID) || !args.containsKey(EXTRA_USERS))
|
||||
return;
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
final String mText = ParseUtils.parseString(mEditText.getText());
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
if (mText == null || mText.length() <= 0 || twitter == null) return;
|
||||
twitter.addUserListMembersAsync(args.getLong(EXTRA_ACCOUNT_ID), args.getLong(EXTRA_LIST_ID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
final View view = LayoutInflater.from(wrapped).inflate(R.layout.auto_complete_textview, null);
|
||||
builder.setView(view);
|
||||
mEditText = (AutoCompleteTextView) view.findViewById(R.id.edit_text);
|
||||
if (savedInstanceState != null) {
|
||||
mEditText.setText(savedInstanceState.getCharSequence(EXTRA_TEXT));
|
||||
}
|
||||
mUserAutoCompleteAdapter = new UserHashtagAutoCompleteAdapter(wrapped);
|
||||
mEditText.setAdapter(mUserAutoCompleteAdapter);
|
||||
mEditText.setThreshold(1);
|
||||
mEditText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(20) });
|
||||
builder.setTitle(R.string.screen_name);
|
||||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, this);
|
||||
return builder.create();
|
||||
}
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
final View view = LayoutInflater.from(wrapped).inflate(R.layout.auto_complete_textview, null);
|
||||
builder.setView(view);
|
||||
mEditText = (AutoCompleteTextView) view.findViewById(R.id.edit_text);
|
||||
if (savedInstanceState != null) {
|
||||
mEditText.setText(savedInstanceState.getCharSequence(EXTRA_TEXT));
|
||||
}
|
||||
mUserAutoCompleteAdapter = new UserHashtagAutoCompleteAdapter(wrapped);
|
||||
final Bundle args = getArguments();
|
||||
mUserAutoCompleteAdapter.setAccountId(args.getLong(EXTRA_ACCOUNT_ID));
|
||||
mEditText.setAdapter(mUserAutoCompleteAdapter);
|
||||
mEditText.setThreshold(1);
|
||||
mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(20)});
|
||||
builder.setTitle(R.string.screen_name);
|
||||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, this);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle outState) {
|
||||
outState.putCharSequence(EXTRA_TEXT, mEditText.getText());
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle outState) {
|
||||
outState.putCharSequence(EXTRA_TEXT, mEditText.getText());
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
public static AddUserListMemberDialogFragment show(final FragmentManager fm, final long accountId, final long listId) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putLong(EXTRA_ACCOUNT_ID, accountId);
|
||||
args.putLong(EXTRA_LIST_ID, listId);
|
||||
final AddUserListMemberDialogFragment f = new AddUserListMemberDialogFragment();
|
||||
f.setArguments(args);
|
||||
f.show(fm, FRAGMENT_TAG);
|
||||
return f;
|
||||
}
|
||||
public static AddUserListMemberDialogFragment show(final FragmentManager fm, final long accountId, final long listId) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putLong(EXTRA_ACCOUNT_ID, accountId);
|
||||
args.putLong(EXTRA_LIST_ID, listId);
|
||||
final AddUserListMemberDialogFragment f = new AddUserListMemberDialogFragment();
|
||||
f.setArguments(args);
|
||||
f.show(fm, FRAGMENT_TAG);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ import org.mariotaku.twidere.util.TwidereValidator;
|
||||
import org.mariotaku.twidere.util.UserColorNameUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
|
||||
import org.mariotaku.twidere.view.StatusComposeEditText;
|
||||
import org.mariotaku.twidere.view.StatusTextCountView;
|
||||
import org.mariotaku.twidere.view.iface.IColorLabelView;
|
||||
|
||||
@ -110,7 +111,7 @@ import java.util.Locale;
|
||||
import static org.mariotaku.twidere.util.Utils.buildDirectMessageConversationUri;
|
||||
import static org.mariotaku.twidere.util.Utils.showOkMessage;
|
||||
|
||||
public class DirectMessagesConversationFragment extends BaseSupportFragment implements
|
||||
public class MessagesConversationFragment extends BaseSupportFragment implements
|
||||
LoaderCallbacks<Cursor>, TextWatcher, OnClickListener, OnItemSelectedListener,
|
||||
OnEditorActionListener, MenuButtonClickListener, PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
@ -126,7 +127,7 @@ public class DirectMessagesConversationFragment extends BaseSupportFragment impl
|
||||
|
||||
private RecyclerView mMessagesListView;
|
||||
private ListView mUsersSearchList;
|
||||
private EditText mEditText;
|
||||
private StatusComposeEditText mEditText;
|
||||
private StatusTextCountView mTextCountView;
|
||||
private View mSendButton;
|
||||
private ImageView mAddImageButton;
|
||||
@ -238,6 +239,7 @@ public class DirectMessagesConversationFragment extends BaseSupportFragment impl
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
final ParcelableAccount account = (ParcelableAccount) mAccountSpinner.getSelectedItem();
|
||||
mEditText.setAccountId(account.account_id);
|
||||
searchUsers(account.account_id, ParseUtils.parseString(s), true);
|
||||
}
|
||||
|
||||
@ -611,7 +613,7 @@ public class DirectMessagesConversationFragment extends BaseSupportFragment impl
|
||||
final View inputSendContainer = view.findViewById(R.id.input_send_container);
|
||||
mConversationContainer = view.findViewById(R.id.conversation_container);
|
||||
mRecipientSelectorContainer = view.findViewById(R.id.recipient_selector_container);
|
||||
mEditText = (EditText) inputSendContainer.findViewById(R.id.edit_text);
|
||||
mEditText = (StatusComposeEditText) inputSendContainer.findViewById(R.id.edit_text);
|
||||
mTextCountView = (StatusTextCountView) inputSendContainer.findViewById(R.id.text_count);
|
||||
mSendButton = inputSendContainer.findViewById(R.id.send);
|
||||
mAddImageButton = (ImageView) inputSendContainer.findViewById(R.id.add_image);
|
@ -49,20 +49,27 @@ import android.support.v7.widget.RecyclerView.Adapter;
|
||||
import android.support.v7.widget.RecyclerView.LayoutParams;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.ActionMode;
|
||||
import android.view.ActionMode.Callback;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.URLUtil;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
||||
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
|
||||
import org.mariotaku.twidere.adapter.AbsStatusesAdapter.StatusAdapterListener;
|
||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
||||
@ -81,6 +88,7 @@ import org.mariotaku.twidere.model.SingleResponse;
|
||||
import org.mariotaku.twidere.text.method.StatusContentMovementMethod;
|
||||
import org.mariotaku.twidere.util.AsyncTaskUtils;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ClipboardUtils;
|
||||
import org.mariotaku.twidere.util.CompareUtils;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.LinkCreator;
|
||||
@ -123,9 +131,8 @@ import static org.mariotaku.twidere.util.Utils.showErrorMessage;
|
||||
/**
|
||||
* Created by mariotaku on 14/12/5.
|
||||
*/
|
||||
public class StatusFragment extends BaseSupportFragment
|
||||
implements LoaderCallbacks<SingleResponse<ParcelableStatus>>, OnMediaClickListener,
|
||||
StatusAdapterListener {
|
||||
public class StatusFragment extends BaseSupportFragment implements LoaderCallbacks<SingleResponse<ParcelableStatus>>,
|
||||
OnMediaClickListener, StatusAdapterListener {
|
||||
|
||||
private static final int LOADER_ID_DETAIL_STATUS = 1;
|
||||
private static final int LOADER_ID_STATUS_REPLIES = 2;
|
||||
@ -858,6 +865,10 @@ public class StatusFragment extends BaseSupportFragment
|
||||
updateItemDecoration();
|
||||
}
|
||||
|
||||
private int getStatusPosition() {
|
||||
return getConversationCount();
|
||||
}
|
||||
|
||||
public boolean setStatus(ParcelableStatus status) {
|
||||
final ParcelableStatus old = mStatus;
|
||||
mStatus = status;
|
||||
@ -1084,14 +1095,10 @@ public class StatusFragment extends BaseSupportFragment
|
||||
textView.setText(Html.fromHtml(status.text_html));
|
||||
final StatusLinkClickHandler linkClickHandler = new StatusLinkClickHandler(context, null);
|
||||
linkClickHandler.setStatus(status);
|
||||
final TwidereLinkify linkify = new TwidereLinkify(linkClickHandler);
|
||||
final TwidereLinkify linkify = new TwidereLinkify(linkClickHandler, VALUE_LINK_HIGHLIGHT_OPTION_CODE_BOTH, false);
|
||||
linkify.applyAllLinks(textView, status.account_id, status.is_possibly_sensitive);
|
||||
ThemeUtils.applyParagraphSpacing(textView, 1.1f);
|
||||
|
||||
textView.setMovementMethod(StatusContentMovementMethod.getInstance());
|
||||
// textView.setCustomSelectionActionModeCallback(this);
|
||||
|
||||
|
||||
final String timeString = formatToLongTimeString(context, status.timestamp);
|
||||
final String sourceHtml = status.source;
|
||||
if (!isEmpty(timeString) && !isEmpty(sourceHtml)) {
|
||||
@ -1181,7 +1188,8 @@ public class StatusFragment extends BaseSupportFragment
|
||||
private void initViews() {
|
||||
// menuBar.setOnMenuItemClickListener(this);
|
||||
menuBar.setOnMenuItemClickListener(this);
|
||||
final FragmentActivity activity = adapter.getFragment().getActivity();
|
||||
final StatusFragment fragment = adapter.getFragment();
|
||||
final FragmentActivity activity = fragment.getActivity();
|
||||
final MenuInflater inflater = activity.getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_status, menuBar.getMenu());
|
||||
ThemeUtils.wrapMenuIcon(menuBar, MENU_GROUP_STATUS_SHARE);
|
||||
@ -1197,6 +1205,52 @@ public class StatusFragment extends BaseSupportFragment
|
||||
screenNameView.setTextSize(defaultTextSize * 0.85f);
|
||||
locationView.setTextSize(defaultTextSize * 0.85f);
|
||||
timeSourceView.setTextSize(defaultTextSize * 0.85f);
|
||||
|
||||
textView.setMovementMethod(StatusContentMovementMethod.getInstance());
|
||||
textView.setCustomSelectionActionModeCallback(new Callback() {
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
final FragmentActivity activity = fragment.getActivity();
|
||||
if (activity instanceof IThemedActivity) {
|
||||
final int themeRes = ((IThemedActivity) activity).getCurrentThemeResourceId();
|
||||
final int accentColor = ((IThemedActivity) activity).getCurrentThemeColor();
|
||||
ThemeUtils.applySupportActionModeBackground(mode, fragment.getActivity(), themeRes, accentColor, true);
|
||||
}
|
||||
mode.getMenuInflater().inflate(R.menu.action_status_text_selection, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
final int start = textView.getSelectionStart(), end = textView.getSelectionEnd();
|
||||
final SpannableString string = SpannableString.valueOf(textView.getText());
|
||||
final URLSpan[] spans = string.getSpans(start, end, URLSpan.class);
|
||||
final boolean avail = spans.length == 1 && URLUtil.isValidUrl(spans[0].getURL());
|
||||
Utils.setMenuItemAvailability(menu, android.R.id.copyUrl, avail);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.copyUrl: {
|
||||
final int start = textView.getSelectionStart(), end = textView.getSelectionEnd();
|
||||
final SpannableString string = SpannableString.valueOf(textView.getText());
|
||||
final URLSpan[] spans = string.getSpans(start, end, URLSpan.class);
|
||||
if (spans.length != 1) return true;
|
||||
ClipboardUtils.setText(activity, spans[0].getURL());
|
||||
mode.finish();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -738,7 +738,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
||||
|
||||
getUserInfo(accountId, userId, screenName, false);
|
||||
|
||||
final float actionBarElevation = ThemeUtils.getActionBarElevation(activity);
|
||||
final float actionBarElevation = ThemeUtils.getSupportActionBarElevation(activity);
|
||||
ViewCompat.setElevation(mPagerIndicator, actionBarElevation);
|
||||
|
||||
setupBaseActionBar();
|
||||
|
@ -458,7 +458,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
}
|
||||
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_RELATIONSHIP: {
|
||||
final long accountId = ParseUtils.parseLong(uri.getLastPathSegment(), -1);
|
||||
final SQLSelectQuery query = CachedUsersQueryBuilder.buildWithRelationship(projection,
|
||||
final SQLSelectQuery query = CachedUsersQueryBuilder.withRelationship(projection,
|
||||
selection, sortOrder, accountId);
|
||||
final Cursor c = mDatabaseWrapper.rawQuery(query.getSQL(), selectionArgs);
|
||||
setNotificationUri(c, CachedUsers.CONTENT_URI);
|
||||
@ -466,7 +466,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
}
|
||||
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_SCORE: {
|
||||
final long accountId = ParseUtils.parseLong(uri.getLastPathSegment(), -1);
|
||||
final SQLSelectQuery query = CachedUsersQueryBuilder.buildWithScore(projection,
|
||||
final SQLSelectQuery query = CachedUsersQueryBuilder.withScore(projection,
|
||||
selection, sortOrder, accountId);
|
||||
final Cursor c = mDatabaseWrapper.rawQuery(query.getSQL(), selectionArgs);
|
||||
setNotificationUri(c, CachedUsers.CONTENT_URI);
|
||||
|
@ -19,20 +19,16 @@
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.text.ClipboardManager;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public final class ClipboardUtils {
|
||||
|
||||
public static CharSequence getText(final Context context) {
|
||||
if (context == null) return null;
|
||||
return ((ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE)).getText();
|
||||
}
|
||||
|
||||
public static boolean setText(final Context context, final CharSequence text) {
|
||||
if (context == null) return false;
|
||||
((ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE)).setText(text != null ? text : "");
|
||||
return true;
|
||||
}
|
||||
public static boolean setText(final Context context, final CharSequence text) {
|
||||
if (context == null) return false;
|
||||
final ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(text, text));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
@ -33,10 +33,13 @@ import android.graphics.Typeface;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.internal.app.WindowDecorActionBar;
|
||||
import android.support.v7.internal.app.WindowDecorActionBar.ActionModeImpl;
|
||||
import android.support.v7.internal.view.SupportActionModeWrapper;
|
||||
import android.support.v7.internal.view.SupportActionModeWrapperTrojan;
|
||||
import android.support.v7.internal.view.menu.ActionMenuItemView;
|
||||
import android.support.v7.widget.ActionMenuView;
|
||||
import android.text.SpannableStringBuilder;
|
||||
@ -44,6 +47,7 @@ import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ActionMode;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.Menu;
|
||||
@ -67,6 +71,7 @@ import org.mariotaku.twidere.view.TabPagerIndicator;
|
||||
import org.mariotaku.twidere.view.iface.IThemedView;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class ThemeUtils implements Constants {
|
||||
@ -128,6 +133,35 @@ public class ThemeUtils implements Constants {
|
||||
}
|
||||
}
|
||||
|
||||
public static void applySupportActionModeBackground(ActionMode mode, FragmentActivity activity,
|
||||
int themeRes, int accentColor, boolean outlineEnabled) {
|
||||
// Very dirty implementation
|
||||
if (!(mode instanceof SupportActionModeWrapper) || !(activity instanceof IThemedActivity))
|
||||
return;
|
||||
final android.support.v7.view.ActionMode modeCompat =
|
||||
SupportActionModeWrapperTrojan.getWrappedObject((SupportActionModeWrapper) mode);
|
||||
if (!(modeCompat instanceof ActionModeImpl)) return;
|
||||
try {
|
||||
WindowDecorActionBar actionBar = null;
|
||||
final Field[] fields = ActionModeImpl.class.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (WindowDecorActionBar.class.isAssignableFrom(field.getType())) {
|
||||
field.setAccessible(true);
|
||||
actionBar = (WindowDecorActionBar) field.get(modeCompat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (actionBar == null) return;
|
||||
final Field contextViewField = WindowDecorActionBar.class.getDeclaredField("mContextView");
|
||||
contextViewField.setAccessible(true);
|
||||
final View view = (View) contextViewField.get(actionBar);
|
||||
if (view == null) return;
|
||||
ViewAccessor.setBackground(view, getActionBarBackground(activity, themeRes, accentColor, outlineEnabled));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void initPagerIndicatorAsActionBarTab(FragmentActivity activity, TabPagerIndicator indicator) {
|
||||
final float supportActionBarElevation = getSupportActionBarElevation(activity);
|
||||
ViewCompat.setElevation(indicator, supportActionBarElevation);
|
||||
@ -376,9 +410,11 @@ public class ThemeUtils implements Constants {
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||
public static float getActionBarElevation(final Context context) {
|
||||
final TypedArray a = context.obtainStyledAttributes(null, new int[]{android.R.attr.elevation}, android.R.attr.actionBarStyle, 0);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return 0;
|
||||
@SuppressLint("InlinedApi")
|
||||
final TypedArray a = context.obtainStyledAttributes(null, new int[]{android.R.attr.elevation},
|
||||
android.R.attr.actionBarStyle, 0);
|
||||
try {
|
||||
return a.getDimension(0, 0);
|
||||
} finally {
|
||||
|
@ -100,6 +100,7 @@ public final class TwidereLinkify implements Constants {
|
||||
|
||||
private final OnLinkClickListener mOnLinkClickListener;
|
||||
private final Extractor mExtractor = new Extractor();
|
||||
private final boolean mAddMovementMethod;
|
||||
private int mHighlightOption;
|
||||
|
||||
public TwidereLinkify(final OnLinkClickListener listener) {
|
||||
@ -107,7 +108,12 @@ public final class TwidereLinkify implements Constants {
|
||||
}
|
||||
|
||||
public TwidereLinkify(final OnLinkClickListener listener, final int highlightOption) {
|
||||
this(listener, highlightOption, true);
|
||||
}
|
||||
|
||||
public TwidereLinkify(final OnLinkClickListener listener, final int highlightOption, boolean addMovementMethod) {
|
||||
mOnLinkClickListener = listener;
|
||||
mAddMovementMethod = addMovementMethod;
|
||||
setHighlightOption(highlightOption);
|
||||
}
|
||||
|
||||
|
@ -44,18 +44,18 @@ public class TwidereQueryBuilder {
|
||||
|
||||
public static final class CachedUsersQueryBuilder {
|
||||
|
||||
public static SQLSelectQuery buildWithRelationship(final String[] projection,
|
||||
final String selection,
|
||||
final String sortOrder,
|
||||
final long accountId) {
|
||||
return buildWithRelationship(Utils.getColumnsFromProjection(projection), selection,
|
||||
public static SQLSelectQuery withRelationship(final String[] projection,
|
||||
final String selection,
|
||||
final String sortOrder,
|
||||
final long accountId) {
|
||||
return withRelationship(Utils.getColumnsFromProjection(projection), selection,
|
||||
sortOrder, accountId);
|
||||
}
|
||||
|
||||
public static SQLSelectQuery buildWithRelationship(final Selectable select,
|
||||
final String selection,
|
||||
final String sortOrder,
|
||||
final long accountId) {
|
||||
public static SQLSelectQuery withRelationship(final Selectable select,
|
||||
final String selection,
|
||||
final String sortOrder,
|
||||
final long accountId) {
|
||||
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||
qb.select(select).from(new Tables(CachedUsers.TABLE_NAME));
|
||||
final Column relationshipsUserId = new Column(new Table(CachedRelationships.TABLE_NAME),
|
||||
@ -78,10 +78,10 @@ public class TwidereQueryBuilder {
|
||||
return qb.build();
|
||||
}
|
||||
|
||||
public static SQLSelectQuery buildWithScore(final String[] projection,
|
||||
final String selection,
|
||||
final String sortOrder,
|
||||
final long accountId) {
|
||||
public static SQLSelectQuery withScore(final String[] projection,
|
||||
final String selection,
|
||||
final String sortOrder,
|
||||
final long accountId) {
|
||||
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||
final Selectable select = Utils.getColumnsFromProjection(projection);
|
||||
final Column[] columns = new Column[CachedUsers.COLUMNS.length + 1];
|
||||
@ -99,7 +99,7 @@ public class TwidereQueryBuilder {
|
||||
CachedRelationships.MUTING));
|
||||
columns[columns.length - 1] = new Column(expr, "score");
|
||||
qb.select(select);
|
||||
qb.from(buildWithRelationship(new Columns(columns), null, null, accountId));
|
||||
qb.from(withRelationship(new Columns(columns), null, null, accountId));
|
||||
if (selection != null) {
|
||||
qb.where(new Expression(selection));
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||
import org.mariotaku.twidere.fragment.support.AddStatusFilterDialogFragment;
|
||||
import org.mariotaku.twidere.fragment.support.DestroyStatusDialogFragment;
|
||||
import org.mariotaku.twidere.fragment.support.DirectMessagesConversationFragment;
|
||||
import org.mariotaku.twidere.fragment.support.MessagesConversationFragment;
|
||||
import org.mariotaku.twidere.fragment.support.IncomingFriendshipsFragment;
|
||||
import org.mariotaku.twidere.fragment.support.MutesUsersListFragment;
|
||||
import org.mariotaku.twidere.fragment.support.SavedSearchesListFragment;
|
||||
@ -884,7 +884,7 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
break;
|
||||
}
|
||||
case LINK_ID_DIRECT_MESSAGES_CONVERSATION: {
|
||||
fragment = new DirectMessagesConversationFragment();
|
||||
fragment = new MessagesConversationFragment();
|
||||
final String paramRecipientId = uri.getQueryParameter(QUERY_PARAM_RECIPIENT_ID);
|
||||
final String paramScreenName = uri.getQueryParameter(QUERY_PARAM_SCREEN_NAME);
|
||||
final long conversationId = ParseUtils.parseLong(paramRecipientId);
|
||||
|
@ -34,6 +34,7 @@ import org.mariotaku.twidere.view.themed.ThemedMultiAutoCompleteTextView;
|
||||
public class StatusComposeEditText extends ThemedMultiAutoCompleteTextView implements IThemedView {
|
||||
|
||||
private UserHashtagAutoCompleteAdapter mAdapter;
|
||||
private long mAccountId;
|
||||
|
||||
public StatusComposeEditText(final Context context) {
|
||||
this(context, null);
|
||||
@ -64,10 +65,11 @@ public class StatusComposeEditText extends ThemedMultiAutoCompleteTextView imple
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (!isInEditMode() && (mAdapter == null || mAdapter.isCursorClosed())) {
|
||||
if (!isInEditMode() && mAdapter == null) {
|
||||
mAdapter = new UserHashtagAutoCompleteAdapter(this);
|
||||
}
|
||||
setAdapter(mAdapter);
|
||||
updateAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,7 +79,16 @@ public class StatusComposeEditText extends ThemedMultiAutoCompleteTextView imple
|
||||
mAdapter.closeCursor();
|
||||
mAdapter = null;
|
||||
}
|
||||
// setAdapter(null);
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
mAccountId = accountId;
|
||||
updateAccountId();
|
||||
}
|
||||
|
||||
private void updateAccountId() {
|
||||
if (mAdapter == null) return;
|
||||
mAdapter.setAccountId(mAccountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user