copy link now work

fixed user auto completion
This commit is contained in:
Mariotaku Lee 2015-04-04 05:12:33 +08:00
parent 8fc291fda5
commit 8d6c2629a1
18 changed files with 285 additions and 116 deletions

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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());
}

View File

@ -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;
}
}

View File

@ -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));

View File

@ -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) {

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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) {
}
});
}

View File

@ -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();

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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);

View File

@ -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