implementing keyboard shortcut
removed some unused sources
This commit is contained in:
parent
3d75fbbfd0
commit
809876c050
|
@ -34,4 +34,18 @@
|
|||
<!--Twitter for Google TV-->
|
||||
<item>56d8f9ff</item>
|
||||
</string-array>
|
||||
<string-array name="names_official_consumer_secret_crc32">
|
||||
<!--Twitter for Android-->
|
||||
<item>Twitter for Android</item>
|
||||
<!--Twitter for iPhone-->
|
||||
<item>Twitter for iPhone</item>
|
||||
<!--Twitter for iPad-->
|
||||
<item>Twitter for iPad</item>
|
||||
<!--Twitter for Mac-->
|
||||
<item>Twitter for Mac</item>
|
||||
<!--Twitter for Windows Phone-->
|
||||
<item>Twitter for Windows Phone</item>
|
||||
<!--Twitter for Google TV-->
|
||||
<item>Twitter for Google TV</item>
|
||||
</string-array>
|
||||
</resources>
|
|
@ -33,7 +33,7 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
|||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||
import org.mariotaku.twidere.fragment.iface.IBasePullToRefreshFragment;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
||||
import org.mariotaku.twidere.util.MessagesManager;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.view.iface.IExtendedView.OnFitSystemWindowsListener;
|
||||
|
@ -42,7 +42,8 @@ import java.util.ArrayList;
|
|||
|
||||
@SuppressLint("Registered")
|
||||
public class BaseActionBarActivity extends ThemedActionBarActivity implements Constants,
|
||||
OnFitSystemWindowsListener, SystemWindowsInsetsCallback, IControlBarActivity {
|
||||
OnFitSystemWindowsListener, SystemWindowsInsetsCallback, IControlBarActivity,
|
||||
ShortcutCallback {
|
||||
|
||||
private boolean mInstanceStateSaved, mIsVisible, mIsOnTop;
|
||||
|
||||
|
@ -118,7 +119,8 @@ public class BaseActionBarActivity extends ThemedActionBarActivity implements Co
|
|||
return null;
|
||||
}
|
||||
|
||||
protected boolean handleKeyboardShortcut(int keyCode,@NonNull KeyEvent event) {
|
||||
@Override
|
||||
public boolean handleKeyboardShortcut(int keyCode, @NonNull KeyEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ import org.mariotaku.twidere.util.ColorUtils;
|
|||
import org.mariotaku.twidere.util.CustomTabUtils;
|
||||
import org.mariotaku.twidere.util.FlymeUtils;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
||||
import org.mariotaku.twidere.util.MathUtils;
|
||||
import org.mariotaku.twidere.util.MultiSelectEventHandler;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
|
@ -279,9 +280,16 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleKeyboardShortcut(int keyCode, @NonNull KeyEvent event) {
|
||||
mKeyboardShortcutsHandler.handleKey(null, keyCode, event);
|
||||
return super.handleKeyboardShortcut(keyCode, event);
|
||||
public boolean handleKeyboardShortcut(int keyCode, @NonNull KeyEvent event) {
|
||||
if (handleCurrentFragmentKeyboardShortcut(keyCode, event)) return true;
|
||||
return mKeyboardShortcutsHandler.handleKey(this, null, keyCode, event);
|
||||
}
|
||||
|
||||
private boolean handleCurrentFragmentKeyboardShortcut(int keyCode, @NonNull KeyEvent event) {
|
||||
if (mCurrentVisibleFragment instanceof ShortcutCallback) {
|
||||
return ((ShortcutCallback) mCurrentVisibleFragment).handleKeyboardShortcut(keyCode, event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -301,10 +309,11 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
}
|
||||
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mTwitterWrapper = getTwitterWrapper();
|
||||
mReadStateManager = TwidereApplication.getInstance(this).getReadStateManager();
|
||||
final TwidereApplication app = TwidereApplication.getInstance(this);
|
||||
mReadStateManager = app.getReadStateManager();
|
||||
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
mMultiSelectHandler = new MultiSelectEventHandler(this);
|
||||
mKeyboardShortcutsHandler = new KeyboardShortcutsHandler(this);
|
||||
mKeyboardShortcutsHandler = app.getKeyboardShortcutsHandler();
|
||||
mMultiSelectHandler.dispatchOnCreate();
|
||||
final long[] accountIds = getAccountIds(this);
|
||||
if (accountIds.length == 0) {
|
||||
|
|
|
@ -25,26 +25,26 @@ import android.graphics.Rect;
|
|||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.support.v4.view.WindowCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.iface.IControlBarActivity;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||
import org.mariotaku.twidere.fragment.iface.IBasePullToRefreshFragment;
|
||||
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
|
||||
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
|
||||
import org.mariotaku.twidere.fragment.support.SearchFragment;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
||||
import org.mariotaku.twidere.util.MultiSelectEventHandler;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
@ -55,13 +55,16 @@ import org.mariotaku.twidere.view.TintedStatusFrameLayout;
|
|||
import static org.mariotaku.twidere.util.Utils.createFragmentForIntent;
|
||||
import static org.mariotaku.twidere.util.Utils.matchLinkId;
|
||||
|
||||
public class LinkHandlerActivity extends BaseActionBarActivity implements OnClickListener,
|
||||
OnLongClickListener, SystemWindowsInsetsCallback, IControlBarActivity, SupportFragmentCallback {
|
||||
public class LinkHandlerActivity extends BaseActionBarActivity implements SystemWindowsInsetsCallback,
|
||||
IControlBarActivity, SupportFragmentCallback {
|
||||
|
||||
private ControlBarShowHideHelper mControlBarShowHideHelper = new ControlBarShowHideHelper(this);
|
||||
|
||||
private MultiSelectEventHandler mMultiSelectHandler;
|
||||
private KeyboardShortcutsHandler mKeyboardShortcutsHandler;
|
||||
|
||||
private TintedStatusFrameLayout mMainContent;
|
||||
|
||||
private boolean mFinishOnly;
|
||||
|
||||
@Override
|
||||
|
@ -84,35 +87,6 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.go_top: {
|
||||
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_content);
|
||||
if (fragment instanceof RefreshScrollTopInterface) {
|
||||
((RefreshScrollTopInterface) fragment).scrollToStart();
|
||||
} else if (fragment instanceof ListFragment) {
|
||||
((ListFragment) fragment).setSelection(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(final View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.go_top: {
|
||||
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_content);
|
||||
if (fragment instanceof RefreshScrollTopInterface) {
|
||||
((RefreshScrollTopInterface) fragment).triggerRefresh();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
@ -150,6 +124,7 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
|
|||
final int linkId = matchLinkId(data);
|
||||
requestWindowFeatures(getWindow(), linkId, data);
|
||||
super.onCreate(savedInstanceState);
|
||||
mKeyboardShortcutsHandler = TwidereApplication.getInstance(this).getKeyboardShortcutsHandler();
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
@ -411,6 +386,19 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
|
|||
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyboardShortcut(int keyCode, @NonNull KeyEvent event) {
|
||||
if (handleCurrentFragmentKeyboardShortcut(keyCode, event)) return true;
|
||||
return mKeyboardShortcutsHandler.handleKey(this, null, keyCode, event);
|
||||
}
|
||||
|
||||
private boolean handleCurrentFragmentKeyboardShortcut(int keyCode, @NonNull KeyEvent event) {
|
||||
final Fragment fragment = getCurrentVisibleFragment();
|
||||
if (fragment instanceof ShortcutCallback) {
|
||||
return ((ShortcutCallback) fragment).handleKeyboardShortcut(keyCode, event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlBarOffset(float offset) {
|
||||
|
|
|
@ -72,6 +72,7 @@ import org.mariotaku.twidere.util.ThemeUtils;
|
|||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.VideoLoader;
|
||||
import org.mariotaku.twidere.util.VideoLoader.VideoLoadingListener;
|
||||
import org.mariotaku.twidere.view.LinePageIndicator;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
@ -82,6 +83,7 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
private MediaPagerAdapter mAdapter;
|
||||
private ActionBar mActionBar;
|
||||
private View mMediaStatusContainer;
|
||||
private LinePageIndicator mIndicator;
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -124,6 +126,7 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
public void onSupportContentChanged() {
|
||||
super.onSupportContentChanged();
|
||||
mViewPager = (ViewPager) findViewById(R.id.view_pager);
|
||||
mIndicator = (LinePageIndicator) findViewById(R.id.pager_indicator);
|
||||
mMediaStatusContainer = findViewById(R.id.media_status_container);
|
||||
}
|
||||
|
||||
|
@ -137,16 +140,19 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
mViewPager.setAdapter(mAdapter);
|
||||
mViewPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.element_spacing_normal));
|
||||
mViewPager.setOnPageChangeListener(this);
|
||||
mIndicator.setSelectedColor(getCurrentThemeColor());
|
||||
mIndicator.setViewPager(mViewPager);
|
||||
final Intent intent = getIntent();
|
||||
final long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
|
||||
final ParcelableMedia[] media = Utils.newParcelableArray(intent.getParcelableArrayExtra(EXTRA_MEDIA), ParcelableMedia.CREATOR);
|
||||
final ParcelableMedia currentMedia = intent.getParcelableExtra(EXTRA_CURRENT_MEDIA);
|
||||
mAdapter.setMedia(accountId, media);
|
||||
mIndicator.notifyDataSetChanged();
|
||||
final int currentIndex = ArrayUtils.indexOf(media, currentMedia);
|
||||
if (currentIndex != -1) {
|
||||
mViewPager.setCurrentItem(currentIndex, false);
|
||||
}
|
||||
if (intent.hasExtra(EXTRA_STATUS)) {
|
||||
if (isMediaStatusEnabled() && intent.hasExtra(EXTRA_STATUS)) {
|
||||
mMediaStatusContainer.setVisibility(View.VISIBLE);
|
||||
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
final Fragment f = new ViewStatusDialogFragment();
|
||||
|
@ -175,9 +181,15 @@ public final class MediaViewerActivity extends ThemedActionBarActivity implement
|
|||
mActionBar.hide();
|
||||
}
|
||||
|
||||
mMediaStatusContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
mIndicator.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
mMediaStatusContainer.setVisibility(isMediaStatusEnabled() && visible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private boolean isMediaStatusEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void toggleBar() {
|
||||
setBarVisibility(!isBarShowing());
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.mariotaku.twidere.activity.MainHondaJOJOActivity;
|
|||
import org.mariotaku.twidere.service.RefreshService;
|
||||
import org.mariotaku.twidere.util.AsyncTaskManager;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MessagesManager;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
|
@ -97,6 +98,7 @@ public class TwidereApplication extends MultiDexApplication implements Constants
|
|||
private Bus mMessageBus;
|
||||
private VideoLoader mVideoLoader;
|
||||
private ReadStateManager mReadStateManager;
|
||||
private KeyboardShortcutsHandler mKeyboardShortcutsHandler;
|
||||
|
||||
private String mDefaultUserAgent;
|
||||
|
||||
|
@ -138,6 +140,15 @@ public class TwidereApplication extends MultiDexApplication implements Constants
|
|||
return mReadStateManager = new ReadStateManager(this);
|
||||
}
|
||||
|
||||
public KeyboardShortcutsHandler getKeyboardShortcutsHandler() {
|
||||
if (mKeyboardShortcutsHandler != null) return mKeyboardShortcutsHandler;
|
||||
mKeyboardShortcutsHandler = new KeyboardShortcutsHandler(this);
|
||||
if (mKeyboardShortcutsHandler.isEmpty()) {
|
||||
mKeyboardShortcutsHandler.reset();
|
||||
}
|
||||
return mKeyboardShortcutsHandler;
|
||||
}
|
||||
|
||||
public ImageDownloader getImageDownloader() {
|
||||
if (mImageDownloader != null) return mImageDownloader;
|
||||
return mImageDownloader = new TwidereImageDownloader(this, false, true);
|
||||
|
|
|
@ -19,109 +19,55 @@
|
|||
|
||||
package org.mariotaku.twidere.fragment;
|
||||
|
||||
import android.app.LoaderManager.LoaderCallbacks;
|
||||
import android.content.AsyncTaskLoader;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnKeyListener;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.ActionMode;
|
||||
import android.preference.DialogPreference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView.MultiChoiceModeListener;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.ArrayAdapter;
|
||||
import org.mariotaku.twidere.model.KeyboardShortcutSpec;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutSpec;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/10.
|
||||
*/
|
||||
public class KeyboardShortcutsFragment extends BaseListFragment implements LoaderCallbacks<List<KeyboardShortcutSpec>>, MultiChoiceModeListener {
|
||||
public class KeyboardShortcutsFragment extends BasePreferenceFragment {
|
||||
|
||||
private Adapter mAdapter;
|
||||
private ListView mListView;
|
||||
private KeyboardShortcutsHandler mKeyboardShortcutHandler;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
mAdapter = new Adapter(getActivity());
|
||||
setListAdapter(mAdapter);
|
||||
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
|
||||
mListView.setMultiChoiceModeListener(this);
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
setListShown(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.action_multi_select_items, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
updateTitle(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_DELETE: {
|
||||
final SharedPreferences.Editor editor = getSharedPreferences(KEYBOARD_SHORTCUTS_PREFERENCES_NAME, Context.MODE_PRIVATE).edit();
|
||||
final SparseBooleanArray array = mListView.getCheckedItemPositions();
|
||||
if (array == null) return false;
|
||||
for (int i = 0, size = array.size(); i < size; i++) {
|
||||
if (array.valueAt(i)) {
|
||||
editor.remove(mAdapter.getItem(i).getRawKey());
|
||||
}
|
||||
}
|
||||
editor.apply();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
final Activity activity = getActivity();
|
||||
mKeyboardShortcutHandler = TwidereApplication.getInstance(activity).getKeyboardShortcutsHandler();
|
||||
final PreferenceScreen defaultScreen = getPreferenceScreen();
|
||||
final PreferenceScreen preferenceScreen;
|
||||
if (defaultScreen != null) {
|
||||
defaultScreen.removeAll();
|
||||
preferenceScreen = defaultScreen;
|
||||
} else {
|
||||
preferenceScreen = getPreferenceManager().createPreferenceScreen(activity);
|
||||
}
|
||||
mode.finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<List<KeyboardShortcutSpec>> onCreateLoader(int id, Bundle args) {
|
||||
return new KeyboardShortcutSpecsLoader(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<KeyboardShortcutSpec>> loader, List<KeyboardShortcutSpec> data) {
|
||||
mAdapter.clear();
|
||||
mAdapter.addAll(data);
|
||||
setListShown(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<List<KeyboardShortcutSpec>> loader) {
|
||||
|
||||
setPreferenceScreen(preferenceScreen);
|
||||
addPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -129,95 +75,138 @@ public class KeyboardShortcutsFragment extends BaseListFragment implements Loade
|
|||
inflater.inflate(R.menu.menu_keyboard_shortcuts, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_ADD: {
|
||||
final SharedPreferences preferences = getSharedPreferences(KEYBOARD_SHORTCUTS_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final Editor editor = preferences.edit();
|
||||
editor.putString("ctrl+m", "compose");
|
||||
editor.apply();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
private void addPreferences() {
|
||||
final PreferenceCategory general = makeAndAddCategory(getString(R.string.general));
|
||||
general.addPreference(makePreferences(null, "compose"));
|
||||
general.addPreference(makePreferences(null, "search"));
|
||||
general.addPreference(makePreferences(null, "message"));
|
||||
final PreferenceCategory statuses = makeAndAddCategory(getString(R.string.statuses));
|
||||
statuses.addPreference(makePreferences("status", "status.reply"));
|
||||
statuses.addPreference(makePreferences("status", "status.retweet"));
|
||||
statuses.addPreference(makePreferences("status", "status.favorite"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
|
||||
|
||||
private PreferenceCategory makeAndAddCategory(String title) {
|
||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
final Context context = preferenceScreen.getContext();
|
||||
//noinspection ConstantConditions
|
||||
final PreferenceCategory category = new PreferenceCategory(context, null);
|
||||
category.setTitle(title);
|
||||
preferenceScreen.addPreference(category);
|
||||
return category;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mListView = getListView();
|
||||
private KeyboardShortcutPreferences makePreferences(String contextTag, String action) {
|
||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
final Context context = preferenceScreen.getContext();
|
||||
return new KeyboardShortcutPreferences(context, mKeyboardShortcutHandler, contextTag, action);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
private static class KeyboardShortcutPreferences extends DialogPreference implements OnKeyListener {
|
||||
|
||||
private static class Adapter extends ArrayAdapter<KeyboardShortcutSpec> {
|
||||
private final KeyboardShortcutsHandler mKeyboardShortcutHandler;
|
||||
private final String mContextTag, mAction;
|
||||
private final OnSharedPreferenceChangeListener mPreferencesChangeListener;
|
||||
private TextView mKeysLabel, mConflictLabel;
|
||||
private KeyboardShortcutSpec mKeySpec;
|
||||
|
||||
public Adapter(Context context) {
|
||||
super(context, android.R.layout.simple_list_item_activated_2);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
final View view = super.getView(position, convertView, parent);
|
||||
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
|
||||
final TextView text2 = (TextView) view.findViewById(android.R.id.text2);
|
||||
final KeyboardShortcutSpec spec = getItem(position);
|
||||
text1.setText(spec.getValueName(getContext()));
|
||||
text2.setText(spec.toKeyString());
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class KeyboardShortcutSpecsLoader extends AsyncTaskLoader<List<KeyboardShortcutSpec>> {
|
||||
private final SharedPreferences preferences;
|
||||
private final OnSharedPreferenceChangeListener changeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
forceLoad();
|
||||
}
|
||||
};
|
||||
|
||||
public KeyboardShortcutSpecsLoader(Context context) {
|
||||
super(context);
|
||||
preferences = context.getSharedPreferences(KEYBOARD_SHORTCUTS_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
preferences.registerOnSharedPreferenceChangeListener(changeListener);
|
||||
public KeyboardShortcutPreferences(final Context context, final KeyboardShortcutsHandler handler,
|
||||
@Nullable final String contextTag, @NonNull final String action) {
|
||||
//noinspection ConstantConditions
|
||||
super(context, null);
|
||||
mKeyboardShortcutHandler = handler;
|
||||
mContextTag = contextTag;
|
||||
mAction = action;
|
||||
setDialogLayoutResource(R.layout.dialog_keyboard_shortcut_input);
|
||||
setPersistent(false);
|
||||
setDialogTitle(KeyboardShortcutsHandler.getActionLabel(context, action));
|
||||
setTitle(KeyboardShortcutsHandler.getActionLabel(context, action));
|
||||
mPreferencesChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
updateSummary();
|
||||
}
|
||||
};
|
||||
updateSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyboardShortcutSpec> loadInBackground() {
|
||||
final ArrayList<KeyboardShortcutSpec> list = new ArrayList<>();
|
||||
for (Entry<String, ?> entry : preferences.getAll().entrySet()) {
|
||||
final KeyboardShortcutSpec spec = new KeyboardShortcutSpec(entry.getKey(), ParseUtils.parseString(entry.getValue()));
|
||||
if (spec.isValid()) {
|
||||
list.add(spec);
|
||||
protected void onAttachedToActivity() {
|
||||
super.onAttachedToActivity();
|
||||
mKeyboardShortcutHandler.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareForRemoval() {
|
||||
mKeyboardShortcutHandler.unregisterOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
super.onPrepareForRemoval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
if (mKeySpec == null) return;
|
||||
mKeyboardShortcutHandler.register(mKeySpec, mAction);
|
||||
break;
|
||||
}
|
||||
case DialogInterface.BUTTON_NEUTRAL: {
|
||||
mKeyboardShortcutHandler.unregister(mAction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
forceLoad();
|
||||
protected void onPrepareDialogBuilder(Builder builder) {
|
||||
builder.setPositiveButton(getContext().getString(android.R.string.ok), this);
|
||||
builder.setNegativeButton(getContext().getString(android.R.string.cancel), this);
|
||||
builder.setNeutralButton(getContext().getString(R.string.clear), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
if (isAbandoned()) {
|
||||
preferences.unregisterOnSharedPreferenceChangeListener(changeListener);
|
||||
protected void showDialog(Bundle state) {
|
||||
super.showDialog(state);
|
||||
final Dialog dialog = getDialog();
|
||||
dialog.setOnKeyListener(this);
|
||||
mKeysLabel = (TextView) dialog.findViewById(R.id.keys_label);
|
||||
mConflictLabel = (TextView) dialog.findViewById(R.id.conflict_label);
|
||||
|
||||
mConflictLabel.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (event.getAction() != KeyEvent.ACTION_UP) return false;
|
||||
if (event.hasNoModifiers() && keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
|
||||
mKeyboardShortcutHandler.unregister(mAction);
|
||||
return true;
|
||||
}
|
||||
super.onReset();
|
||||
final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(mContextTag, keyCode, event);
|
||||
if (spec == null || !spec.isValid()) return false;
|
||||
mKeySpec = spec;
|
||||
mKeysLabel.setText(spec.toKeyString());
|
||||
final String oldAction = mKeyboardShortcutHandler.findAction(spec);
|
||||
final Context context = getContext();
|
||||
if (mAction.equals(oldAction) || TextUtils.isEmpty(oldAction)) {
|
||||
mConflictLabel.setVisibility(View.GONE);
|
||||
if (dialog instanceof AlertDialog) {
|
||||
((AlertDialog) dialog).setButton(DialogInterface.BUTTON_POSITIVE, context.getString(android.R.string.ok), this);
|
||||
}
|
||||
} else {
|
||||
mConflictLabel.setVisibility(View.VISIBLE);
|
||||
final String label = KeyboardShortcutsHandler.getActionLabel(context, oldAction);
|
||||
mConflictLabel.setText(context.getString(R.string.conflicts_with_name, label));
|
||||
if (dialog instanceof AlertDialog) {
|
||||
((AlertDialog) dialog).setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.overwrite), this);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateSummary() {
|
||||
final KeyboardShortcutSpec spec = mKeyboardShortcutHandler.findKey(mAction);
|
||||
setSummary(spec != null ? spec.toKeyString() : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
|
@ -19,6 +20,7 @@ import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
|
|||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.RecyclerView.OnScrollListener;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
@ -44,6 +46,8 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
|||
import org.mariotaku.twidere.util.ColorUtils;
|
||||
import org.mariotaku.twidere.util.ContentListScrollListener;
|
||||
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListSupport;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
||||
import org.mariotaku.twidere.util.ReadStateManager;
|
||||
import org.mariotaku.twidere.util.SimpleDrawerCallback;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
@ -63,7 +67,7 @@ import static org.mariotaku.twidere.util.Utils.setMenuForStatus;
|
|||
*/
|
||||
public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment implements LoaderCallbacks<Data>,
|
||||
OnRefreshListener, DrawerCallback, RefreshScrollTopInterface, StatusAdapterListener,
|
||||
ControlBarOffsetListener, ContentListSupport {
|
||||
ControlBarOffsetListener, ContentListSupport, ShortcutCallback {
|
||||
|
||||
private final Object mStatusesBusCallback;
|
||||
private AbsStatusesAdapter<Data> mAdapter;
|
||||
|
@ -77,6 +81,7 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
private int mControlBarOffsetPixels;
|
||||
private PopupMenu mPopupMenu;
|
||||
private ReadStateManager mReadStateManager;
|
||||
private KeyboardShortcutsHandler mKeyboardShortcutsHandler;
|
||||
private ParcelableStatus mSelectedStatus;
|
||||
private OnMenuItemClickListener mOnStatusMenuItemClickListener = new OnMenuItemClickListener() {
|
||||
@Override
|
||||
|
@ -117,6 +122,40 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
return mDrawerCallback.isScrollContent(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyboardShortcut(int keyCode, @NonNull KeyEvent event) {
|
||||
if (!KeyboardShortcutsHandler.isValidForHotkey(keyCode, event)) return false;
|
||||
final View focusedChild = mLayoutManager.getFocusedChild();
|
||||
final int position = mRecyclerView.getChildLayoutPosition(focusedChild);
|
||||
if (position == -1) return false;
|
||||
final ParcelableStatus status = mAdapter.getStatus(position);
|
||||
if (status == null) return false;
|
||||
final String action = mKeyboardShortcutsHandler.getKeyAction("status", keyCode, event);
|
||||
if (action == null) return false;
|
||||
switch (action) {
|
||||
case "status.reply": {
|
||||
final Intent intent = new Intent(INTENT_ACTION_REPLY);
|
||||
intent.putExtra(EXTRA_STATUS, status);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
case "status.retweet": {
|
||||
RetweetQuoteDialogFragment.show(getFragmentManager(), status);
|
||||
return true;
|
||||
}
|
||||
case "status.favorite": {
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status);
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollBy(float dy) {
|
||||
mDrawerCallback.scrollBy(dy);
|
||||
|
@ -175,6 +214,9 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
mReadStateManager = getReadStateManager();
|
||||
final FragmentActivity activity = getActivity();
|
||||
final TwidereApplication application = TwidereApplication.getInstance(activity);
|
||||
mKeyboardShortcutsHandler = application.getKeyboardShortcutsHandler();
|
||||
final View view = getView();
|
||||
if (view == null) throw new AssertionError();
|
||||
final Context context = view.getContext();
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.model;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/11.
|
||||
*/
|
||||
public class KeyboardShortcutSpec {
|
||||
|
||||
private String rawKey;
|
||||
private String value;
|
||||
private String contextTag;
|
||||
private int keyMeta;
|
||||
private String keyName;
|
||||
|
||||
public KeyboardShortcutSpec(String key, String value) {
|
||||
rawKey = key;
|
||||
final int contextDotIdx = key.indexOf('.');
|
||||
if (contextDotIdx != -1) {
|
||||
contextTag = key.substring(0, contextDotIdx);
|
||||
}
|
||||
int idx = contextDotIdx, previousIdx = idx;
|
||||
while ((idx = key.indexOf('+', idx + 1)) != -1) {
|
||||
keyMeta |= KeyboardShortcutsHandler.getKeyEventMeta(key.substring(previousIdx + 1, idx));
|
||||
previousIdx = idx;
|
||||
}
|
||||
if (previousIdx != -1) {
|
||||
keyName = key.substring(previousIdx + 1);
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getContextTag() {
|
||||
return contextTag;
|
||||
}
|
||||
|
||||
public int getKeyMeta() {
|
||||
return keyMeta;
|
||||
}
|
||||
|
||||
public String getKeyName() {
|
||||
return keyName;
|
||||
}
|
||||
|
||||
public String getRawKey() {
|
||||
return rawKey;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getValueName(Context context) {
|
||||
return KeyboardShortcutsHandler.getActionLabel(context, value);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return keyName != null;
|
||||
}
|
||||
|
||||
public String toKeyString() {
|
||||
return KeyboardShortcutsHandler.metaToHumanReadableString(keyMeta) + keyName.toUpperCase(Locale.US);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KeyboardShortcutSpec{" +
|
||||
"value='" + value + '\'' +
|
||||
", contextTag='" + contextTag + '\'' +
|
||||
", keyMeta=" + keyMeta +
|
||||
", keyName='" + keyName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -196,6 +196,21 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public int createFavoriteAsync(final ParcelableStatus status) {
|
||||
//spice
|
||||
final Context context = getContext();
|
||||
SpiceProfilingUtil.profile(context,
|
||||
status.account_id, status.id + ",Favor,"
|
||||
+ status.account_id + "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(context, status.id + ",Favor,"
|
||||
+ status.account_id + "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count + "," + status.timestamp);
|
||||
//end
|
||||
return createFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
|
||||
public int createFriendshipAsync(final long accountId, final long userId) {
|
||||
final CreateFriendshipTask task = new CreateFriendshipTask(accountId, userId);
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
|
@ -252,6 +267,22 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public int destroyFavoriteAsync(final ParcelableStatus status) {
|
||||
//spice
|
||||
final Context context = getContext();
|
||||
SpiceProfilingUtil.profile(context,
|
||||
status.account_id, status.id + ",Unfavor," + status.account_id
|
||||
+ "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(context, status.id + ",Unfavor," + status.account_id
|
||||
+ "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
//end
|
||||
return destroyFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
|
||||
public int destroyFriendshipAsync(final long accountId, final long user_id) {
|
||||
final DestroyFriendshipTask task = new DestroyFriendshipTask(accountId, user_id);
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
|
@ -579,7 +610,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
Utils.showErrorMessage(mContext, R.string.action_updating_profile_banner_image, result.getException(),
|
||||
true);
|
||||
}
|
||||
} @Override
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SingleResponse<ParcelableUser> doInBackground(final Object... params) {
|
||||
try {
|
||||
final Twitter twitter = getTwitterInstance(mContext, mAccountId, true);
|
||||
|
@ -599,7 +632,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static class UpdateProfileImageTask extends ManagedAsyncTask<Object, Object, SingleResponse<ParcelableUser>> {
|
||||
|
@ -1379,7 +1411,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
final TwitterException te = (TwitterException) e;
|
||||
return te.getErrorCode() == StatusCodeMessageUtils.PAGE_NOT_FOUND
|
||||
|| te.getStatusCode() == HttpResponseCode.NOT_FOUND;
|
||||
} @Override
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SingleResponse<DirectMessage> doInBackground(final Object... args) {
|
||||
final Twitter twitter = getTwitterInstance(mContext, account_id, false);
|
||||
if (twitter == null) return SingleResponse.getInstance();
|
||||
|
@ -1396,7 +1430,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final SingleResponse<DirectMessage> result) {
|
||||
super.onPostExecute(result);
|
||||
|
@ -1769,7 +1802,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
|
||||
protected abstract Uri getDatabaseUri();
|
||||
|
||||
protected abstract boolean isOutgoing(); @Override
|
||||
protected abstract boolean isOutgoing();
|
||||
|
||||
@Override
|
||||
protected List<MessageListResponse> doInBackground(final Object... params) {
|
||||
|
||||
final List<MessageListResponse> result = new ArrayList<>();
|
||||
|
@ -1843,7 +1878,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
|
@ -1871,14 +1905,15 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
public ResponseList<twitter4j.Status> getStatuses(final Twitter twitter, final Paging paging)
|
||||
throws TwitterException {
|
||||
return twitter.getHomeTimeline(paging);
|
||||
} @NonNull
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Uri getDatabaseUri() {
|
||||
return Statuses.CONTENT_URI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final List<StatusListResponse> result) {
|
||||
super.onPostExecute(result);
|
||||
|
@ -1966,13 +2001,14 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
public ResponseList<DirectMessage> getDirectMessages(final Twitter twitter, final Paging paging)
|
||||
throws TwitterException {
|
||||
return twitter.getDirectMessages(paging);
|
||||
} @Override
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Uri getDatabaseUri() {
|
||||
return Inbox.CONTENT_URI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean isOutgoing() {
|
||||
return false;
|
||||
|
@ -2044,7 +2080,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
|
||||
final boolean isMaxIdsValid() {
|
||||
return mMaxIds != null && mMaxIds.length == mAccountIds.length;
|
||||
} @SafeVarargs
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
@Override
|
||||
protected final void onProgressUpdate(TwitterListResponse<twitter4j.Status>... values) {
|
||||
AsyncTaskUtils.executeTask(new CacheUsersStatusesTask(mContext), values);
|
||||
|
|
|
@ -42,22 +42,13 @@ public class ContentListScrollListener extends OnScrollListener {
|
|||
mContentListSupport = contentListSupport;
|
||||
}
|
||||
|
||||
public void setOnScrollListener(OnScrollListener listener) {
|
||||
mOnScrollListener = listener;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
if (mOnScrollListener != null) {
|
||||
mOnScrollListener.onScrollStateChanged(recyclerView, newState);
|
||||
}
|
||||
final IContentCardAdapter adapter = mContentListSupport.getAdapter();
|
||||
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (!mContentListSupport.isRefreshing() && adapter.isLoadMoreSupported()
|
||||
&& !adapter.isLoadMoreIndicatorVisible() && mScrollState != RecyclerView.SCROLL_STATE_IDLE
|
||||
&& layoutManager.findLastVisibleItemPosition() == adapter.getItemCount() - 1) {
|
||||
mContentListSupport.onLoadMoreContents();
|
||||
if (mScrollState != RecyclerView.SCROLL_STATE_IDLE) {
|
||||
notifyScrollStateChanged(recyclerView);
|
||||
}
|
||||
mScrollState = newState;
|
||||
}
|
||||
|
@ -76,22 +67,37 @@ public class ContentListScrollListener extends OnScrollListener {
|
|||
mContentListSupport.setControlVisible(dy < 0);
|
||||
mScrollSum = 0;
|
||||
}
|
||||
if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
notifyScrollStateChanged(recyclerView);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnScrollListener(OnScrollListener listener) {
|
||||
mOnScrollListener = listener;
|
||||
}
|
||||
|
||||
public void setTouchSlop(int touchSlop) {
|
||||
mTouchSlop = touchSlop;
|
||||
}
|
||||
|
||||
public static interface ContentListSupport {
|
||||
private void notifyScrollStateChanged(RecyclerView recyclerView) {
|
||||
final IContentCardAdapter adapter = mContentListSupport.getAdapter();
|
||||
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (!mContentListSupport.isRefreshing() && adapter.isLoadMoreSupported() && !adapter.isLoadMoreIndicatorVisible()
|
||||
&& layoutManager.findLastVisibleItemPosition() == adapter.getItemCount() - 1) {
|
||||
mContentListSupport.onLoadMoreContents();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRefreshing();
|
||||
public static interface ContentListSupport {
|
||||
|
||||
IContentCardAdapter getAdapter();
|
||||
|
||||
void setControlVisible(boolean visible);
|
||||
boolean isRefreshing();
|
||||
|
||||
void onLoadMoreContents();
|
||||
|
||||
void setControlVisible(boolean visible);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@ package org.mariotaku.twidere.util;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.SparseArrayCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
|
@ -10,19 +14,37 @@ import org.mariotaku.twidere.Constants;
|
|||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.support.ComposeActivity;
|
||||
import org.mariotaku.twidere.activity.support.QuickSearchBarActivity;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public class KeyboardShortcutsHandler implements Constants {
|
||||
|
||||
public String findAction(@NonNull KeyboardShortcutSpec spec) {
|
||||
return mPreferences.getString(spec.getRawKey(), null);
|
||||
}
|
||||
|
||||
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
|
||||
mPreferences.registerOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
|
||||
mPreferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
private static final HashMap<String, Integer> sActionLabelMap = new HashMap<>();
|
||||
private static final SparseArrayCompat<String> sMetaNameMap = new SparseArrayCompat<>();
|
||||
|
||||
static {
|
||||
sActionLabelMap.put("compose", R.string.compose);
|
||||
sActionLabelMap.put("search", R.string.search);
|
||||
sActionLabelMap.put("message", R.string.new_direct_message);
|
||||
sActionLabelMap.put("status.reply", R.string.reply);
|
||||
sActionLabelMap.put("status.retweet", R.string.retweet);
|
||||
sActionLabelMap.put("status.favorite", R.string.favorite);
|
||||
|
||||
sMetaNameMap.put(KeyEvent.META_FUNCTION_ON, "fn");
|
||||
sMetaNameMap.put(KeyEvent.META_META_ON, "meta");
|
||||
|
@ -35,6 +57,16 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
private final Context mContext;
|
||||
private final SharedPreferencesWrapper mPreferences;
|
||||
|
||||
public KeyboardShortcutSpec findKey(String action) {
|
||||
for (Entry<String, ?> entry : mPreferences.getAll().entrySet()) {
|
||||
if (action.equals(entry.getValue())) {
|
||||
final KeyboardShortcutSpec spec = new KeyboardShortcutSpec(entry.getKey(), action);
|
||||
if (spec.isValid()) return spec;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getKeyEventMeta(String name) {
|
||||
for (int i = 0, j = sMetaNameMap.size(); i < j; i++) {
|
||||
if (sMetaNameMap.valueAt(i).equalsIgnoreCase(name)) return sMetaNameMap.keyAt(i);
|
||||
|
@ -42,7 +74,7 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public KeyboardShortcutsHandler(final Context context) {
|
||||
public KeyboardShortcutsHandler(final TwidereApplication context) {
|
||||
mContext = context;
|
||||
mPreferences = SharedPreferencesWrapper.getInstance(context, KEYBOARD_SHORTCUTS_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
@ -71,6 +103,7 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
}
|
||||
|
||||
public static String getKeyEventKey(String contextTag, int keyCode, KeyEvent event) {
|
||||
if (!isValidForHotkey(keyCode, event)) return null;
|
||||
final StringBuilder keyNameBuilder = new StringBuilder();
|
||||
if (!TextUtils.isEmpty(contextTag)) {
|
||||
keyNameBuilder.append(contextTag);
|
||||
|
@ -91,26 +124,196 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
return keyNameBuilder.toString();
|
||||
}
|
||||
|
||||
public boolean handleKey(final String contextTag, final int keyCode, final KeyEvent event) {
|
||||
public static String getKeyEventKey(String contextTag, int metaState, String keyName) {
|
||||
final StringBuilder keyNameBuilder = new StringBuilder();
|
||||
if (!TextUtils.isEmpty(contextTag)) {
|
||||
keyNameBuilder.append(contextTag);
|
||||
keyNameBuilder.append(".");
|
||||
}
|
||||
|
||||
for (int i = 0, j = sMetaNameMap.size(); i < j; i++) {
|
||||
if ((sMetaNameMap.keyAt(i) & metaState) != 0) {
|
||||
keyNameBuilder.append(sMetaNameMap.valueAt(i));
|
||||
keyNameBuilder.append("+");
|
||||
}
|
||||
}
|
||||
keyNameBuilder.append(keyName);
|
||||
return keyNameBuilder.toString();
|
||||
}
|
||||
|
||||
public static KeyboardShortcutSpec getKeyboardShortcutSpec(String contextTag, int keyCode, KeyEvent event) {
|
||||
if (!isValidForHotkey(keyCode, event)) return null;
|
||||
final int metaState = KeyEvent.normalizeMetaState(event.getMetaState());
|
||||
int metaStateNormalized = 0;
|
||||
for (int i = 0, j = sMetaNameMap.size(); i < j; i++) {
|
||||
if ((sMetaNameMap.keyAt(i) & metaState) != 0) {
|
||||
metaStateNormalized |= sMetaNameMap.keyAt(i);
|
||||
}
|
||||
}
|
||||
final String keyCodeString = KeyEvent.keyCodeToString(keyCode);
|
||||
if (keyCodeString.startsWith(KEYCODE_STRING_PREFIX)) {
|
||||
final String keyName = keyCodeString.substring(KEYCODE_STRING_PREFIX.length()).toLowerCase(Locale.US);
|
||||
return new KeyboardShortcutSpec(contextTag, metaStateNormalized, keyName, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean handleKey(final Context context, final String contextTag, final int keyCode, final KeyEvent event) {
|
||||
if (!isValidForHotkey(keyCode, event)) return false;
|
||||
final String key = getKeyEventKey(contextTag, keyCode, event);
|
||||
final String action = mPreferences.getString(key, null);
|
||||
if (action == null) return false;
|
||||
switch (action) {
|
||||
case "compose": {
|
||||
mContext.startActivity(new Intent(mContext, ComposeActivity.class).setAction(INTENT_ACTION_COMPOSE));
|
||||
context.startActivity(new Intent(context, ComposeActivity.class).setAction(INTENT_ACTION_COMPOSE));
|
||||
return true;
|
||||
}
|
||||
case "search": {
|
||||
mContext.startActivity(new Intent(mContext, QuickSearchBarActivity.class).setAction(INTENT_ACTION_QUICK_SEARCH));
|
||||
context.startActivity(new Intent(context, QuickSearchBarActivity.class).setAction(INTENT_ACTION_QUICK_SEARCH));
|
||||
return true;
|
||||
}
|
||||
case "message": {
|
||||
Utils.openMessageConversation(context, -1, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getKeyAction(final String contextTag, final int keyCode, final KeyEvent event) {
|
||||
if (!isValidForHotkey(keyCode, event)) return null;
|
||||
final String key = getKeyEventKey(contextTag, keyCode, event);
|
||||
return mPreferences.getString(key, null);
|
||||
}
|
||||
|
||||
public static boolean isValidForHotkey(int keyCode, KeyEvent event) {
|
||||
// These keys must use with modifiers
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
case KeyEvent.KEYCODE_NUMPAD_ENTER:
|
||||
case KeyEvent.KEYCODE_TAB: {
|
||||
if (event.hasNoModifiers()) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return !event.isSystem() && !KeyEvent.isModifierKey(keyCode) && keyCode != KeyEvent.KEYCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return mPreferences.getAll().isEmpty();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
final Editor editor = mPreferences.edit();
|
||||
editor.clear();
|
||||
editor.putString("n", "compose");
|
||||
editor.putString("m", "message");
|
||||
editor.putString("slash", "search");
|
||||
editor.putString("status.f", "status.favorite");
|
||||
editor.putString("status.r", "status.reply");
|
||||
editor.putString("status.t", "status.retweet");
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public void register(KeyboardShortcutSpec spec, String action) {
|
||||
unregister(action);
|
||||
mPreferences.edit().putString(spec.getRawKey(), action).apply();
|
||||
}
|
||||
|
||||
public void unregister(String action) {
|
||||
final Editor editor = mPreferences.edit();
|
||||
for (Entry<String, ?> entry : mPreferences.getAll().entrySet()) {
|
||||
if (action.equals(entry.getValue())) {
|
||||
final KeyboardShortcutSpec spec = new KeyboardShortcutSpec(entry.getKey(), action);
|
||||
if (spec.isValid()) {
|
||||
editor.remove(spec.getRawKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static interface ShortcutCallback {
|
||||
boolean handleKeyboardShortcut(int keyCode, @NonNull KeyEvent event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/11.
|
||||
*/
|
||||
public static class KeyboardShortcutSpec {
|
||||
|
||||
private String action;
|
||||
private String contextTag;
|
||||
private int keyMeta;
|
||||
private String keyName;
|
||||
|
||||
public KeyboardShortcutSpec(String contextTag, int keyMeta, String keyName, String action) {
|
||||
this.contextTag = contextTag;
|
||||
this.keyMeta = keyMeta;
|
||||
this.keyName = keyName;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public KeyboardShortcutSpec(String key, String action) {
|
||||
final int contextDotIdx = key.indexOf('.');
|
||||
if (contextDotIdx != -1) {
|
||||
contextTag = key.substring(0, contextDotIdx);
|
||||
}
|
||||
int idx = contextDotIdx, previousIdx = idx;
|
||||
while ((idx = key.indexOf('+', idx + 1)) != -1) {
|
||||
keyMeta |= getKeyEventMeta(key.substring(previousIdx + 1, idx));
|
||||
previousIdx = idx;
|
||||
}
|
||||
keyName = key.substring(previousIdx + 1);
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getContextTag() {
|
||||
return contextTag;
|
||||
}
|
||||
|
||||
public int getKeyMeta() {
|
||||
return keyMeta;
|
||||
}
|
||||
|
||||
public String getKeyName() {
|
||||
return keyName;
|
||||
}
|
||||
|
||||
public String getRawKey() {
|
||||
return getKeyEventKey(contextTag, keyMeta, keyName);
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public String getValueName(Context context) {
|
||||
return getActionLabel(context, action);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return keyName != null;
|
||||
}
|
||||
|
||||
public String toKeyString() {
|
||||
return metaToHumanReadableString(keyMeta) + keyName.toUpperCase(Locale.US);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KeyboardShortcutSpec{" +
|
||||
"action='" + action + '\'' +
|
||||
", contextTag='" + contextTag + '\'' +
|
||||
", keyMeta=" + keyMeta +
|
||||
", keyName='" + keyName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,7 +243,6 @@ import java.util.zip.CRC32;
|
|||
import javax.net.ssl.SSLException;
|
||||
|
||||
import edu.tsinghua.spice.SpiceService;
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
import edu.ucdavis.earlybird.UCDService;
|
||||
import twitter4j.DirectMessage;
|
||||
import twitter4j.RateLimitStatus;
|
||||
|
@ -2925,9 +2924,9 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void openMessageConversation(final FragmentActivity activity, final long accountId,
|
||||
public static void openMessageConversation(final Context context, final long accountId,
|
||||
final long recipientId) {
|
||||
if (activity == null) return;
|
||||
if (context == null) return;
|
||||
final Uri.Builder builder = new Uri.Builder();
|
||||
builder.scheme(SCHEME_TWIDERE);
|
||||
builder.authority(AUTHORITY_DIRECT_MESSAGES_CONVERSATION);
|
||||
|
@ -2936,7 +2935,7 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
builder.appendQueryParameter(QUERY_PARAM_RECIPIENT_ID, String.valueOf(recipientId));
|
||||
}
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
|
||||
activity.startActivity(intent);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void openMedia(final Context context, final ParcelableDirectMessage message, final ParcelableMedia current) {
|
||||
|
@ -3569,15 +3568,9 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
}
|
||||
final MenuItem retweet = menu.findItem(MENU_RETWEET);
|
||||
if (retweet != null) {
|
||||
retweet.setVisible(!status.user_is_protected || isMyRetweet);
|
||||
ActionIconDrawable.setMenuHighlight(retweet, new TwidereMenuInfo(isMyRetweet, retweetHighlight));
|
||||
retweet.setTitle(isMyRetweet ? R.string.cancel_retweet : R.string.retweet);
|
||||
}
|
||||
// final MenuItem retweetSubItem = menu.findItem(R.id.retweet_submenu);
|
||||
// if (retweetSubItem != null) {
|
||||
// ActionIconDrawable.setMenuHighlight(retweetSubItem, new TwidereMenuInfo(isMyRetweet,
|
||||
// retweetHighlight));
|
||||
// }
|
||||
final MenuItem favorite = menu.findItem(MENU_FAVORITE);
|
||||
if (favorite != null) {
|
||||
ActionIconDrawable.setMenuHighlight(favorite, new TwidereMenuInfo(status.is_favorite, favoriteHighlight));
|
||||
|
@ -3950,30 +3943,9 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
}
|
||||
case MENU_FAVORITE: {
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(context,
|
||||
status.account_id, status.id + ",Unfavor," + status.account_id
|
||||
+ "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(context, status.id + ",Unfavor," + status.account_id
|
||||
+ "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
//end
|
||||
twitter.destroyFavoriteAsync(status);
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status.account_id, status.id);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(context,
|
||||
status.account_id, status.id + ",Favor,"
|
||||
+ status.account_id + "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(context, status.id + ",Favor,"
|
||||
+ status.account_id + "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count + "," + status.timestamp);
|
||||
//end
|
||||
twitter.createFavoriteAsync(status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class ActionBarHomeAsUpIndicator extends ImageView {
|
||||
|
||||
public ActionBarHomeAsUpIndicator(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionBarHomeAsUpIndicator(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ActionBarHomeAsUpIndicator(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
final TypedArray a = context.obtainStyledAttributes(new int[]{android.R.attr.homeAsUpIndicator});
|
||||
final Drawable d = a.getDrawable(0);
|
||||
a.recycle();
|
||||
setImageDrawable(d);
|
||||
setScaleType(ScaleType.CENTER);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.accessor.ViewAccessor;
|
||||
|
||||
public class ActionBarSplitThemedContainer extends FrameLayout {
|
||||
|
||||
public ActionBarSplitThemedContainer(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionBarSplitThemedContainer(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ActionBarSplitThemedContainer(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.layout});
|
||||
final int resId = a.getResourceId(0, 0);
|
||||
a.recycle();
|
||||
if (resId == 0)
|
||||
throw new IllegalArgumentException("You must specify a layout resource in layout XML file.");
|
||||
final View view = LayoutInflater.from(getThemedContext(context)).inflate(resId, this, false);
|
||||
final int themeResId = ThemeUtils.getThemeResource(context);
|
||||
ViewAccessor.setBackground(view, ThemeUtils.getActionBarSplitBackground(context, themeResId));
|
||||
addView(view);
|
||||
}
|
||||
|
||||
private static Context getThemedContext(final Context context) {
|
||||
return ThemeUtils.getActionBarContext(context);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class ActionBarSubtitleView extends TextView {
|
||||
|
||||
public ActionBarSubtitleView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionBarSubtitleView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ActionBarSubtitleView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
final TypedArray a = context.obtainStyledAttributes(null, new int[]{android.R.attr.subtitleTextStyle},
|
||||
android.R.attr.actionBarStyle, android.R.style.Widget_Holo_ActionBar);
|
||||
final int textAppearance = a.getResourceId(0, android.R.style.Widget_Holo_ActionBar);
|
||||
a.recycle();
|
||||
setTextAppearance(context, textAppearance);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
|
||||
public class ActionBarTabView extends FrameLayout {
|
||||
|
||||
private CharSequence mTitle;
|
||||
private Drawable mIcon;
|
||||
|
||||
public ActionBarTabView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionBarTabView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.actionBarTabStyle);
|
||||
}
|
||||
|
||||
public ActionBarTabView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
inflate(context, R.layout.tab_item_ab, this);
|
||||
}
|
||||
|
||||
public void setIcon(final Drawable icon) {
|
||||
mIcon = icon;
|
||||
setIconView(icon);
|
||||
}
|
||||
|
||||
public void setIcon(final int iconRes) {
|
||||
setIcon(getResources().getDrawable(iconRes));
|
||||
}
|
||||
|
||||
public void setIconView(final Drawable icon) {
|
||||
final ImageView iconView = (ImageView) findViewById(android.R.id.icon);
|
||||
if (iconView == null) return;
|
||||
iconView.setVisibility(icon != null ? GONE : VISIBLE);
|
||||
iconView.setImageDrawable(icon);
|
||||
}
|
||||
|
||||
public void setTitle(final CharSequence title) {
|
||||
mTitle = title;
|
||||
setTitleView(title);
|
||||
}
|
||||
|
||||
public void setTitle(final int titleRes) {
|
||||
setTitle(getResources().getText(titleRes));
|
||||
}
|
||||
|
||||
public void setTitleView(final CharSequence title) {
|
||||
final TextView titleView = (TextView) findViewById(android.R.id.title);
|
||||
final ImageView iconView = (ImageView) findViewById(android.R.id.icon);
|
||||
if (titleView == null || iconView == null) return;
|
||||
titleView.setVisibility(TextUtils.isEmpty(title) ? GONE : VISIBLE);
|
||||
titleView.setText(title);
|
||||
iconView.setContentDescription(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
setTitleView(mTitle);
|
||||
setIconView(mIcon);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
||||
public class ActionBarThemedContainer extends FrameLayout {
|
||||
|
||||
public ActionBarThemedContainer(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionBarThemedContainer(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ActionBarThemedContainer(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.layout});
|
||||
final int resId = a.getResourceId(0, 0);
|
||||
a.recycle();
|
||||
if (resId == 0)
|
||||
throw new IllegalArgumentException("You must specify a layout resource in layout XML file.");
|
||||
inflate(getThemedContext(context), resId, this);
|
||||
}
|
||||
|
||||
private static Context getThemedContext(final Context context) {
|
||||
return ThemeUtils.getActionBarContext(context);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class ActionBarTitleView extends TextView {
|
||||
|
||||
public ActionBarTitleView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionBarTitleView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ActionBarTitleView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
final TypedArray a = context.obtainStyledAttributes(null, new int[]{android.R.attr.titleTextStyle},
|
||||
android.R.attr.actionBarStyle, android.R.style.Widget_Holo_ActionBar);
|
||||
final int textAppearance = a.getResourceId(0, android.R.style.Widget_Holo_TextView);
|
||||
a.recycle();
|
||||
setTextAppearance(context, textAppearance);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/3/30.
|
||||
*/
|
||||
public class AdvancedRecyclerView extends RecyclerView {
|
||||
public AdvancedRecyclerView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AdvancedRecyclerView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public AdvancedRecyclerView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTrackballEvent(MotionEvent event) {
|
||||
Log.d(Constants.LOGTAG, event.toString());
|
||||
return super.dispatchTrackballEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTrackballEvent(MotionEvent event) {
|
||||
final LayoutManager lm = getLayoutManager();
|
||||
if (!(lm instanceof LinearLayoutManager)) return false;
|
||||
final LinearLayoutManager llm = (LinearLayoutManager) lm;
|
||||
Log.d(Constants.LOGTAG, event.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class AutoAdjustHeightImageView extends ImageView {
|
||||
|
||||
public AutoAdjustHeightImageView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public AutoAdjustHeightImageView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public AutoAdjustHeightImageView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setScaleType(ScaleType.CENTER_CROP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||
final int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
final Drawable d = getDrawable();
|
||||
final Bitmap b = d instanceof BitmapDrawable ? ((BitmapDrawable) d).getBitmap() : null;
|
||||
|
||||
if (b != null) {
|
||||
final int height = Math.round((float) width * (float) b.getHeight() / b.getWidth());
|
||||
setMeasuredDimension(width, height);
|
||||
} else {
|
||||
setMeasuredDimension(width, width);
|
||||
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/12/4.
|
||||
*/
|
||||
public class BottomDividerFrameLayout extends FrameLayout {
|
||||
|
||||
private final Drawable mDividerDrawable;
|
||||
|
||||
public BottomDividerFrameLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BottomDividerFrameLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BottomDividerFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setWillNotDraw(false);
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.divider});
|
||||
mDividerDrawable = a.getDrawable(0);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
final Drawable divider = mDividerDrawable;
|
||||
if (divider != null) {
|
||||
divider.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
final Drawable divider = mDividerDrawable;
|
||||
if (divider != null) {
|
||||
final int drawableLeft = 0, drawableRight = drawableLeft + getMeasuredWidth();
|
||||
final int drawableBottom = getMeasuredHeight(), drawableTop = drawableBottom - divider.getIntrinsicHeight();
|
||||
divider.setBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/11/5.
|
||||
*/
|
||||
public class DrawerAccountHeaderContainer extends RelativeLayout {
|
||||
public DrawerAccountHeaderContainer(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public DrawerAccountHeaderContainer(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DrawerAccountHeaderContainer(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||
final int width = MeasureSpec.getSize(widthMeasureSpec), height = width / 2;
|
||||
setMeasuredDimension(width, height);
|
||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
|
||||
}
|
||||
}
|
|
@ -47,7 +47,7 @@ public class ExtendedFrameLayout extends FrameLayout implements IExtendedView {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final boolean dispatchTouchEvent(final MotionEvent event) {
|
||||
public final boolean dispatchTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
|
@ -80,39 +80,16 @@ public class ExtendedFrameLayout extends FrameLayout implements IExtendedView {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
||||
// if (mOnFitSystemWindowsListener != null && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
|
||||
// mOnFitSystemWindowsListener.onFitSystemWindows(insets);
|
||||
// }
|
||||
if (mOnFitSystemWindowsListener != null) {
|
||||
mOnFitSystemWindowsListener.onFitSystemWindows(insets);
|
||||
}
|
||||
return super.fitSystemWindows(insets);
|
||||
}
|
||||
|
||||
Rect insets = new Rect();
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
// if (mOnFitSystemWindowsListener != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
// final OnFitSystemWindowsListener l = mOnFitSystemWindowsListener;
|
||||
// final Activity activity = Utils.findActivity(getContext());
|
||||
// if (activity instanceof ActionBarActivity) {
|
||||
// final ActionBarActivity actionBarActivity = (ActionBarActivity) activity;
|
||||
// insets.top = Utils.getActionBarHeight(actionBarActivity.getSupportActionBar());
|
||||
// l.onFitSystemWindows(insets);
|
||||
// } else if (activity != null && activity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR
|
||||
// | Window.FEATURE_ACTION_BAR_OVERLAY)) {
|
||||
// insets.top = Utils.getActionBarHeight(activity.getActionBar());
|
||||
// l.onFitSystemWindows(insets);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onTouchEvent(final MotionEvent event) {
|
||||
public final boolean onTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
|
@ -120,6 +97,11 @@ public class ExtendedFrameLayout extends FrameLayout implements IExtendedView {
|
|||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
|
|
@ -62,6 +62,7 @@ public class ExtendedImageView extends ImageView implements IExtendedView {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
||||
if (mOnFitSystemWindowsListener != null) {
|
||||
mOnFitSystemWindowsListener.onFitSystemWindows(insets);
|
||||
|
@ -70,7 +71,7 @@ public class ExtendedImageView extends ImageView implements IExtendedView {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final boolean dispatchTouchEvent(final MotionEvent event) {
|
||||
public final boolean dispatchTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
|
@ -79,7 +80,7 @@ public class ExtendedImageView extends ImageView implements IExtendedView {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final boolean onTouchEvent(final MotionEvent event) {
|
||||
public final boolean onTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
|
|
|
@ -47,7 +47,7 @@ public class ExtendedLinearLayout extends LinearLayout implements IExtendedView
|
|||
}
|
||||
|
||||
@Override
|
||||
public final boolean dispatchTouchEvent(final MotionEvent event) {
|
||||
public final boolean dispatchTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
|
@ -80,6 +80,7 @@ public class ExtendedLinearLayout extends LinearLayout implements IExtendedView
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
||||
if (mOnFitSystemWindowsListener != null) {
|
||||
mOnFitSystemWindowsListener.onFitSystemWindows(insets);
|
||||
|
|
|
@ -47,7 +47,7 @@ public class ExtendedRelativeLayout extends RelativeLayout implements IExtendedV
|
|||
}
|
||||
|
||||
@Override
|
||||
public final boolean dispatchTouchEvent(final MotionEvent event) {
|
||||
public final boolean dispatchTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
|
@ -80,6 +80,7 @@ public class ExtendedRelativeLayout extends RelativeLayout implements IExtendedV
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
||||
if (mOnFitSystemWindowsListener != null) {
|
||||
mOnFitSystemWindowsListener.onFitSystemWindows(insets);
|
||||
|
@ -88,7 +89,7 @@ public class ExtendedRelativeLayout extends RelativeLayout implements IExtendedV
|
|||
}
|
||||
|
||||
@Override
|
||||
public final boolean onTouchEvent(final MotionEvent event) {
|
||||
public final boolean onTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class MapImageView extends ForegroundImageView {
|
||||
|
||||
public MapImageView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public MapImageView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public MapImageView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||
final int width = MeasureSpec.getSize(widthMeasureSpec), height = width / 2;
|
||||
final int hSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
|
||||
super.onMeasure(widthMeasureSpec, hSpec);
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
||||
public class MessageCardItemFrameLayout extends FrameLayout {
|
||||
|
||||
public MessageCardItemFrameLayout(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public MessageCardItemFrameLayout(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public MessageCardItemFrameLayout(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
if (isInEditMode()) return;
|
||||
ThemeUtils.applyThemeAlphaToDrawable(context, getBackground());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
final Drawable d = getBackground();
|
||||
if (d != null && d.isStateful()) {
|
||||
final int[] state = getDrawableState();
|
||||
d.setState(state);
|
||||
final Drawable current = d.getCurrent();
|
||||
if (current instanceof TransitionDrawable) {
|
||||
final TransitionDrawable td = (TransitionDrawable) current;
|
||||
if (ArrayUtils.contains(state, android.R.attr.state_pressed)) {
|
||||
td.startTransition(ViewConfiguration.getLongPressTimeout());
|
||||
} else {
|
||||
td.resetTransition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
||||
public class NavigationArrowButton extends ImageButton {
|
||||
|
||||
private final int mHighlightColor;
|
||||
|
||||
public NavigationArrowButton(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public NavigationArrowButton(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.imageButtonStyle);
|
||||
}
|
||||
|
||||
public NavigationArrowButton(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mHighlightColor = isInEditMode() ? 0 : ThemeUtils.getUserAccentColor(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
updateColorFilter();
|
||||
}
|
||||
|
||||
private void updateColorFilter() {
|
||||
if (isClickable() && isEnabled() && ArrayUtils.contains(getDrawableState(), android.R.attr.state_pressed)) {
|
||||
setColorFilter(mHighlightColor, Mode.MULTIPLY);
|
||||
} else {
|
||||
clearColorFilter();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.view.MotionEventCompat;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/3/30.
|
||||
*/
|
||||
public class RecyclerViewBackport extends RecyclerView {
|
||||
|
||||
// This value is used when handling generic motion events.
|
||||
private float mScrollFactor = Float.MIN_VALUE;
|
||||
|
||||
public RecyclerViewBackport(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public RecyclerViewBackport(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public RecyclerViewBackport(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||
final LayoutManager lm = getLayoutManager();
|
||||
if (lm == null) {
|
||||
return false;
|
||||
}
|
||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
|
||||
if (event.getAction() == MotionEventCompat.ACTION_SCROLL) {
|
||||
final float vScroll, hScroll;
|
||||
if (lm.canScrollVertically()) {
|
||||
vScroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
|
||||
} else {
|
||||
vScroll = 0f;
|
||||
}
|
||||
if (lm.canScrollHorizontally()) {
|
||||
hScroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
|
||||
} else {
|
||||
hScroll = 0f;
|
||||
}
|
||||
|
||||
if (vScroll != 0 || hScroll != 0) {
|
||||
final float scrollFactor = getScrollFactorBackport();
|
||||
scrollBy((int) (hScroll * scrollFactor), (int) (vScroll * scrollFactor));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ported from View.getVerticalScrollFactor.
|
||||
*/
|
||||
private float getScrollFactorBackport() {
|
||||
if (mScrollFactor == Float.MIN_VALUE) {
|
||||
TypedValue outValue = new TypedValue();
|
||||
if (getContext().getTheme().resolveAttribute(
|
||||
android.R.attr.listPreferredItemHeight, outValue, true)) {
|
||||
mScrollFactor = outValue.getDimension(
|
||||
getContext().getResources().getDisplayMetrics());
|
||||
} else {
|
||||
return 0; //listPreferredItemHeight is not defined, no generic scrolling
|
||||
}
|
||||
|
||||
}
|
||||
return mScrollFactor;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
public class SquareView extends View {
|
||||
|
||||
public SquareView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SquareView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SquareView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||
final int width = MeasureSpec.getSize(widthMeasureSpec), height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
final ViewGroup.LayoutParams lp = getLayoutParams();
|
||||
if (lp.height == ViewGroup.LayoutParams.MATCH_PARENT && lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
|
||||
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(height, height);
|
||||
} else if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT && lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
setMeasuredDimension(width, width);
|
||||
} else {
|
||||
if (width > height) {
|
||||
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(height, height);
|
||||
} else {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
setMeasuredDimension(width, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
public class SquareViewPager extends ViewPager {
|
||||
|
||||
public SquareViewPager(final Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SquareViewPager(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||
final int width = MeasureSpec.getSize(widthMeasureSpec), height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
final ViewGroup.LayoutParams lp = getLayoutParams();
|
||||
if (lp.height == ViewGroup.LayoutParams.MATCH_PARENT && lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
|
||||
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(height, height);
|
||||
} else if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT && lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
setMeasuredDimension(width, width);
|
||||
} else {
|
||||
if (width > height) {
|
||||
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(height, height);
|
||||
} else {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
setMeasuredDimension(width, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ public class StatusTextView extends ThemedTextView implements IExtendedView {
|
|||
super(context, attrs);
|
||||
}
|
||||
|
||||
|
||||
public StatusTextView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
@ -48,6 +49,32 @@ public class StatusTextView extends ThemedTextView implements IExtendedView {
|
|||
mOnSelectionChangeListener = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
if (text == null) {
|
||||
super.setText(null, type);
|
||||
return;
|
||||
}
|
||||
super.setText(new SafeSpannableStringWrapper(text), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged(final int selStart, final int selEnd) {
|
||||
super.onSelectionChanged(selStart, selEnd);
|
||||
if (mOnSelectionChangeListener != null) {
|
||||
mOnSelectionChangeListener.onSelectionChanged(selStart, selEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean fitSystemWindows(@NonNull Rect insets) {
|
||||
if (mOnFitSystemWindowsListener != null) {
|
||||
|
@ -73,21 +100,8 @@ public class StatusTextView extends ThemedTextView implements IExtendedView {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged(final int selStart, final int selEnd) {
|
||||
super.onSelectionChanged(selStart, selEnd);
|
||||
if (mOnSelectionChangeListener != null) {
|
||||
mOnSelectionChangeListener.onSelectionChanged(selStart, selEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
if (text == null) {
|
||||
super.setText(null, type);
|
||||
return;
|
||||
}
|
||||
super.setText(new SafeSpannableStringWrapper(text), type);
|
||||
public interface OnSelectionChangeListener {
|
||||
void onSelectionChanged(int selStart, int selEnd);
|
||||
}
|
||||
|
||||
private static class SafeSpannableStringWrapper extends SpannableString {
|
||||
|
@ -106,17 +120,4 @@ public class StatusTextView extends ThemedTextView implements IExtendedView {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onTouchEvent(@NonNull final MotionEvent event) {
|
||||
if (mTouchInterceptor != null) {
|
||||
final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
|
||||
if (ret) return true;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
public interface OnSelectionChangeListener {
|
||||
void onSelectionChanged(int selStart, int selEnd);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -164,14 +164,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
replyRetweetIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
final int typeIconRes = getUserTypeIconRes(status.user_is_verified, status.user_is_protected);
|
||||
if (typeIconRes != 0) {
|
||||
profileTypeView.setImageResource(typeIconRes);
|
||||
profileTypeView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
profileTypeView.setImageDrawable(null);
|
||||
profileTypeView.setVisibility(View.GONE);
|
||||
}
|
||||
final int typeIconRes;
|
||||
|
||||
if (status.is_quote) {
|
||||
quotedNameView.setText(getUserNickname(context, status.user_id, status.user_name, true));
|
||||
|
@ -202,10 +195,14 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
profileTypeView.setVisibility(View.VISIBLE);
|
||||
profileImageView.setVisibility(View.VISIBLE);
|
||||
loader.displayProfileImage(profileImageView, status.quoted_by_user_profile_image);
|
||||
|
||||
typeIconRes = getUserTypeIconRes(status.quoted_by_user_is_verified, status.quoted_by_user_is_protected);
|
||||
} else {
|
||||
profileTypeView.setVisibility(View.GONE);
|
||||
profileImageView.setVisibility(View.GONE);
|
||||
loader.cancelDisplayTask(profileImageView);
|
||||
|
||||
typeIconRes = 0;
|
||||
}
|
||||
|
||||
final int userColor = UserColorNameUtils.getUserColor(context, status.quoted_by_user_id);
|
||||
|
@ -220,19 +217,30 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
quoteIndicator.setVisibility(View.GONE);
|
||||
|
||||
if (adapter.isProfileImageEnabled()) {
|
||||
final String user_profile_image_url = status.user_profile_image_url;
|
||||
profileTypeView.setVisibility(View.VISIBLE);
|
||||
profileImageView.setVisibility(View.VISIBLE);
|
||||
final String user_profile_image_url = status.user_profile_image_url;
|
||||
loader.displayProfileImage(profileImageView, user_profile_image_url);
|
||||
|
||||
typeIconRes = getUserTypeIconRes(status.user_is_verified, status.user_is_protected);
|
||||
} else {
|
||||
profileTypeView.setVisibility(View.GONE);
|
||||
profileImageView.setVisibility(View.GONE);
|
||||
loader.cancelDisplayTask(profileImageView);
|
||||
|
||||
typeIconRes = 0;
|
||||
}
|
||||
final int userColor = UserColorNameUtils.getUserColor(context, status.user_id);
|
||||
itemContent.drawStart(userColor);
|
||||
}
|
||||
|
||||
if (typeIconRes != 0) {
|
||||
profileTypeView.setImageResource(typeIconRes);
|
||||
profileTypeView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
profileTypeView.setImageDrawable(null);
|
||||
profileTypeView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
if (adapter.shouldShowAccountsColor()) {
|
||||
itemContent.drawEnd(Utils.getAccountColor(context, status.account_id));
|
||||
|
@ -390,20 +398,21 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
quoteIndicator.setColor(UserColorNameUtils.getUserColor(context, user_id));
|
||||
|
||||
if (adapter.isProfileImageEnabled()) {
|
||||
profileTypeView.setVisibility(View.VISIBLE);
|
||||
profileImageView.setVisibility(View.VISIBLE);
|
||||
loader.displayProfileImage(profileImageView, cursor.getString(indices.quoted_by_user_profile_image));
|
||||
|
||||
typeIconRes = getUserTypeIconRes(cursor.getShort(indices.quoted_by_user_is_verified) == 1,
|
||||
cursor.getShort(indices.quoted_by_user_is_protected) == 1);
|
||||
} else {
|
||||
profileTypeView.setVisibility(View.GONE);
|
||||
profileImageView.setVisibility(View.GONE);
|
||||
loader.cancelDisplayTask(profileImageView);
|
||||
|
||||
typeIconRes = 0;
|
||||
}
|
||||
|
||||
final int userColor = UserColorNameUtils.getUserColor(context, cursor.getLong(indices.quoted_by_user_id));
|
||||
itemContent.drawStart(userColor);
|
||||
|
||||
typeIconRes = getUserTypeIconRes(cursor.getShort(indices.quoted_by_user_is_verified) == 1,
|
||||
cursor.getShort(indices.quoted_by_user_is_protected) == 1);
|
||||
} else {
|
||||
nameView.setText(user_name);
|
||||
screenNameView.setText("@" + user_screen_name);
|
||||
|
@ -414,20 +423,21 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
quoteIndicator.setVisibility(View.GONE);
|
||||
|
||||
if (adapter.isProfileImageEnabled()) {
|
||||
final String user_profile_image_url = cursor.getString(indices.user_profile_image_url);
|
||||
profileTypeView.setVisibility(View.VISIBLE);
|
||||
profileImageView.setVisibility(View.VISIBLE);
|
||||
|
||||
final String user_profile_image_url = cursor.getString(indices.user_profile_image_url);
|
||||
loader.displayProfileImage(profileImageView, user_profile_image_url);
|
||||
|
||||
typeIconRes = getUserTypeIconRes(cursor.getShort(indices.is_verified) == 1,
|
||||
cursor.getShort(indices.is_protected) == 1);
|
||||
} else {
|
||||
profileTypeView.setVisibility(View.GONE);
|
||||
profileImageView.setVisibility(View.GONE);
|
||||
loader.cancelDisplayTask(profileImageView);
|
||||
|
||||
typeIconRes = 0;
|
||||
}
|
||||
final int userColor = UserColorNameUtils.getUserColor(context, user_id);
|
||||
itemContent.drawStart(userColor);
|
||||
|
||||
typeIconRes = getUserTypeIconRes(cursor.getShort(indices.is_verified) == 1,
|
||||
cursor.getShort(indices.is_protected) == 1);
|
||||
}
|
||||
|
||||
if (typeIconRes != 0) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.mariotaku.twidere.view.iface;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
~ 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
|
||||
|
@ -18,27 +18,26 @@
|
|||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/go_top"
|
||||
style="?android:actionButtonStyle"
|
||||
<org.mariotaku.twidere.view.ExtendedLinearLayout
|
||||
android:id="@+id/keyboard_shortcut_input"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="4dp">
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/element_spacing_xlarge">
|
||||
|
||||
<org.mariotaku.twidere.view.ActionBarTitleView
|
||||
android:id="@+id/actionbar_title"
|
||||
<TextView
|
||||
android:id="@+id/keys_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"/>
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:text="@string/keyboard_shortcut_hint"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionBarSubtitleView
|
||||
android:id="@+id/actionbar_subtitle"
|
||||
<TextView
|
||||
android:id="@+id/conflict_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:visibility="gone"/>
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
</org.mariotaku.twidere.view.ExtendedLinearLayout>
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -36,7 +37,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
|
@ -49,4 +51,14 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:background="#80000000"/>
|
||||
</LinearLayout>
|
||||
|
||||
<org.mariotaku.twidere.view.LinePageIndicator
|
||||
android:id="@+id/pager_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:padding="@dimen/element_spacing_normal"
|
||||
app:lineWidth="@dimen/line_indicator_line_width_wizard"
|
||||
app:selectedColor="?android:colorActivatedHighlight"
|
||||
app:strokeWidth="@dimen/line_indicator_stroke_width_wizard"/>
|
||||
</FrameLayout>
|
|
@ -19,12 +19,12 @@
|
|||
-->
|
||||
|
||||
<org.mariotaku.twidere.view.ExtendedRelativeLayout
|
||||
android:id="@+id/main_content"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/main_content"
|
||||
android:padding="@dimen/element_spacing_normal">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
|
@ -61,11 +61,15 @@
|
|||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:focusable="true"
|
||||
android:hint="@string/search_hint"
|
||||
android:imeActionLabel="@android:string/search_go"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="text"
|
||||
android:singleLine="true"/>
|
||||
android:singleLine="true">
|
||||
|
||||
<requestFocus/>
|
||||
</EditText>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconButton
|
||||
android:id="@+id/search_submit"
|
||||
|
@ -86,8 +90,8 @@
|
|||
android:id="@+id/suggestions_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
tools:listitem="@layout/list_item_user"
|
||||
android:layout_weight="1"/>
|
||||
android:layout_weight="1"
|
||||
tools:listitem="@layout/list_item_user"/>
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
android:layout_gravity="top"
|
||||
android:padding="@dimen/element_spacing_normal"
|
||||
app:lineWidth="@dimen/line_indicator_line_width_wizard"
|
||||
app:selectedColor="?android:colorActivatedHighlight"
|
||||
app:strokeWidth="@dimen/line_indicator_stroke_width_wizard"/>
|
||||
|
||||
</merge>
|
|
@ -21,6 +21,7 @@
|
|||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
@ -36,7 +37,8 @@
|
|||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -213,87 +215,52 @@
|
|||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_normal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
android:text="@string/name"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<EditText
|
||||
<com.rengwuxian.materialedittext.MaterialEditText
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:inputType="textPersonName"
|
||||
android:maxLength="20"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
app:met_baseColor="?android:textColorPrimary"
|
||||
app:met_floatingLabel="normal"
|
||||
app:met_floatingLabelText="@string/name"
|
||||
app:met_maxCharacters="20"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
android:text="@string/description"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<EditText
|
||||
<com.rengwuxian.materialedittext.MaterialEditText
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:inputType="textMultiLine"
|
||||
android:maxLength="160"
|
||||
android:minLines="4"
|
||||
android:singleLine="false"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
app:met_baseColor="?android:textColorPrimary"
|
||||
app:met_floatingLabel="normal"
|
||||
app:met_floatingLabelText="@string/description"
|
||||
app:met_maxCharacters="160"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:text="@string/location"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<EditText
|
||||
<com.rengwuxian.materialedittext.MaterialEditText
|
||||
android:id="@+id/location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPostalAddress"
|
||||
android:maxLength="30"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
app:met_baseColor="?android:textColorPrimary"
|
||||
app:met_floatingLabel="normal"
|
||||
app:met_floatingLabelText="@string/location"
|
||||
app:met_maxCharacters="30"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:text="@string/url"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<EditText
|
||||
<com.rengwuxian.materialedittext.MaterialEditText
|
||||
android:id="@+id/url"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textUri"
|
||||
android:maxLength="100"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
app:met_baseColor="?android:textColorPrimary"
|
||||
app:met_floatingLabel="normal"
|
||||
app:met_floatingLabelText="@string/url"
|
||||
app:met_maxCharacters="100"/>
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
@ -378,24 +345,18 @@
|
|||
<FrameLayout
|
||||
android:id="@+id/progress_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible"
|
||||
tools:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<!--<org.mariotaku.twidere.view.ActionBarThemedContainer-->
|
||||
<!--android:id="@+id/done_bar_container"-->
|
||||
<!--style="?actionBarStyle"-->
|
||||
<!--android:layout_width="match_parent"-->
|
||||
<!--android:layout_height="?actionBarSize"-->
|
||||
<!--android:layout="@layout/actionbar_custom_view_done_cancel"/>-->
|
||||
|
||||
<org.mariotaku.twidere.view.TwidereToolbar
|
||||
android:id="@+id/done_bar"
|
||||
style="?actionBarStyle"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<org.mariotaku.twidere.view.RecyclerViewBackport
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
@ -31,12 +31,6 @@
|
|||
android:text="@string/phishing_link_warning_message_1"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
<!--<org.mariotaku.twidere.view.AutoAdjustHeightImageView-->
|
||||
<!--android:layout_width="match_parent"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:layout_marginBottom="8dp"-->
|
||||
<!--android:layout_marginTop="8dp"/>-->
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<color name="unread_color">@color/material_red</color>
|
||||
<color name="branding_color">@color/material_cyan</color>
|
||||
<color name="bg_color_tab_pressed">#40808080</color>
|
||||
<color name="bg_color_media_viewer">#a0000000</color>
|
||||
<color name="bg_color_media_viewer">#cc000000</color>
|
||||
<color name="background_color_card_item_dark">#1a1a1a</color>
|
||||
<color name="background_color_card_item_light">#fafafa</color>
|
||||
<color name="background_color_action_bar_dark">#212121</color>
|
||||
|
|
|
@ -738,5 +738,8 @@
|
|||
<string name="N_favorites_quantity_other"><xliff:g id="count">%d</xliff:g> favorites</string>
|
||||
<string name="drafts_hint_messages">Your unsent tweets will goes here</string>
|
||||
<string name="keyboard_shortcuts">Keyboard shortcuts</string>
|
||||
<string name="keyboard_shortcut_hint">Press keys</string>
|
||||
<string name="conflicts_with_name">Conflicts with <xliff:g id="name">%s</xliff:g></string>
|
||||
<string name="overwrite">Overwrite</string>
|
||||
|
||||
</resources>
|
Loading…
Reference in New Issue