improved compose dialog
This commit is contained in:
parent
b92bf74781
commit
e988f54448
|
@ -126,6 +126,8 @@ dependencies {
|
|||
compile 'com.github.mariotaku.ObjectCursor:core:0.9.3'
|
||||
compile fileTree(dir: 'libs/main', include: ['*.jar'])
|
||||
provided 'javax.annotation:jsr250-api:1.0'
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
task svgToDrawable(type: SvgDrawableTask) {
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.mariotaku.twidere.test"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
|
||||
|
||||
<!-- We add an application tag here just so that we can indicate that
|
||||
this package needs to link against the android.test library,
|
||||
which is needed when building test cases. -->
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner"/>
|
||||
</application>
|
||||
|
||||
<!--
|
||||
Specifies the instrumentation test runner used to run the tests.
|
||||
-->
|
||||
<instrumentation
|
||||
android:name="android.test.InstrumentationTestRunner"
|
||||
android:targetPackage="org.mariotaku.twidere"
|
||||
android:label="Tests for org.mariotaku.twidere"/>
|
||||
|
||||
</manifest>
|
|
@ -38,6 +38,7 @@ import org.mariotaku.twidere.R;
|
|||
import org.mariotaku.twidere.nyan.NyanDaydreamService;
|
||||
import org.mariotaku.twidere.nyan.NyanSurfaceHelper;
|
||||
import org.mariotaku.twidere.nyan.NyanWallpaperService;
|
||||
import org.mariotaku.twidere.util.DebugModeUtils;
|
||||
|
||||
public class NyanActivity extends Activity implements Constants, OnLongClickListener, OnSharedPreferenceChangeListener {
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ import com.github.johnpersano.supertoasts.SuperToast.OnDismissListener;
|
|||
import com.nostra13.universalimageloader.utils.IoUtils;
|
||||
import com.twitter.Extractor;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.ArrayRecyclerAdapter;
|
||||
import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter;
|
||||
|
@ -127,6 +128,7 @@ import org.mariotaku.twidere.util.PermissionUtils;
|
|||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.TwidereArrayUtils;
|
||||
import org.mariotaku.twidere.util.TwidereValidator;
|
||||
import org.mariotaku.twidere.util.TwidereViewUtils;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.ActionIconView;
|
||||
|
@ -204,7 +206,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
private int mKeyMetaState;
|
||||
|
||||
// Listeners
|
||||
private LocationListener mLocationListener;
|
||||
private final LocationListener mLocationListener = new ComposeLocationListener(this);
|
||||
|
||||
@Override
|
||||
public int getThemeColor() {
|
||||
|
@ -324,8 +326,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
break;
|
||||
}
|
||||
case R.id.account_selector_button: {
|
||||
final boolean isVisible = mAccountSelectorContainer.getVisibility() == View.VISIBLE;
|
||||
mAccountSelectorContainer.setVisibility(isVisible ? View.GONE : View.VISIBLE);
|
||||
setAccountSelectorVisible(!isAccountSelectorVisible());
|
||||
break;
|
||||
}
|
||||
case R.id.location_container: {
|
||||
|
@ -335,6 +336,10 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isAccountSelectorVisible() {
|
||||
return mAccountSelectorContainer.getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
private void confirmAndUpdateStatus() {
|
||||
if (isQuotingProtectedStatus()) {
|
||||
new RetweetProtectedStatusWarnFragment().show(getSupportFragmentManager(),
|
||||
|
@ -385,36 +390,6 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
contentView.getPaddingRight(), contentView.getPaddingBottom());
|
||||
}
|
||||
|
||||
static class ComposeLocationListener implements LocationListener {
|
||||
|
||||
private final WeakReference<ComposeActivity> mActivityRef;
|
||||
|
||||
ComposeLocationListener(ComposeActivity activity) {
|
||||
mActivityRef = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(final Location location) {
|
||||
final ComposeActivity activity = mActivityRef.get();
|
||||
if (activity == null) return;
|
||||
activity.setRecentLocation(ParcelableLocation.fromLocation(location));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(final String provider) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(final String provider) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(final View v) {
|
||||
switch (v.getId()) {
|
||||
|
@ -447,7 +422,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
break;
|
||||
}
|
||||
case R.id.delete: {
|
||||
AsyncTaskUtils.executeTask(new DeleteImageTask(this));
|
||||
AsyncTaskUtils.executeTask(new DeleteMediaTask(this));
|
||||
break;
|
||||
}
|
||||
case R.id.toggle_sensitive: {
|
||||
|
@ -513,19 +488,28 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
switch (event.getActionMasked()) {
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
switch (ev.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
final Rect rect = new Rect();
|
||||
getWindow().getDecorView().getHitRect(rect);
|
||||
if (!rect.contains(Math.round(event.getX()), Math.round(event.getY()))) {
|
||||
final float x = ev.getRawX(), y = ev.getRawY();
|
||||
if (isAccountSelectorVisible()) {
|
||||
if (!TwidereViewUtils.hitView(x, y, mAccountSelectorButton)) {
|
||||
for (int i = 0, j = mAccountSelector.getChildCount(); i < j; i++) {
|
||||
if (TwidereViewUtils.hitView(x, y, mAccountSelector.getChildAt(i))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
setAccountSelectorVisible(false);
|
||||
return true;
|
||||
}
|
||||
} else if (!TwidereViewUtils.hitView(x, y, getWindow().getDecorView())) {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -600,7 +584,6 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||
mLocationListener = new ComposeLocationListener(this);
|
||||
mResolver = getContentResolver();
|
||||
mValidator = new TwidereValidator(this);
|
||||
setContentView(R.layout.activity_compose);
|
||||
|
@ -830,7 +813,6 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
updateAttachedMediaView();
|
||||
}
|
||||
|
||||
|
||||
private void addMedia(final List<ParcelableMediaUpdate> media) {
|
||||
mMediaPreviewAdapter.addAll(media);
|
||||
updateAttachedMediaView();
|
||||
|
@ -1312,10 +1294,40 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
mSendTextCountView.setTextCount(validatedCount);
|
||||
}
|
||||
|
||||
private static class SetProgressVisibleRunnable implements Runnable {
|
||||
static class ComposeLocationListener implements LocationListener {
|
||||
|
||||
private final ComposeActivity activity;
|
||||
private final boolean visible;
|
||||
final WeakReference<ComposeActivity> mActivityRef;
|
||||
|
||||
ComposeLocationListener(ComposeActivity activity) {
|
||||
mActivityRef = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(final Location location) {
|
||||
final ComposeActivity activity = mActivityRef.get();
|
||||
if (activity == null) return;
|
||||
activity.setRecentLocation(ParcelableLocation.fromLocation(location));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(final String provider) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(final String provider) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class SetProgressVisibleRunnable implements Runnable {
|
||||
|
||||
final ComposeActivity activity;
|
||||
final boolean visible;
|
||||
|
||||
SetProgressVisibleRunnable(ComposeActivity activity, boolean visible) {
|
||||
this.activity = activity;
|
||||
|
@ -1338,9 +1350,9 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
static class AccountIconViewHolder extends ViewHolder implements OnClickListener {
|
||||
|
||||
private final AccountIconsAdapter adapter;
|
||||
private final ShapedImageView iconView;
|
||||
private final TextView nameView;
|
||||
final AccountIconsAdapter adapter;
|
||||
final ShapedImageView iconView;
|
||||
final TextView nameView;
|
||||
|
||||
public AccountIconViewHolder(AccountIconsAdapter adapter, View itemView) {
|
||||
super(itemView);
|
||||
|
@ -1353,8 +1365,11 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
public void showAccount(AccountIconsAdapter adapter, ParcelableAccount account, boolean isSelected) {
|
||||
itemView.setAlpha(isSelected ? 1 : 0.33f);
|
||||
final MediaLoaderWrapper loader = adapter.getImageLoader();
|
||||
loader.displayProfileImage(iconView, account.profile_image_url);
|
||||
if (ObjectUtils.notEqual(account.profile_image_url, iconView.getTag()) || iconView.getDrawable() == null) {
|
||||
loader.displayProfileImage(iconView, account.profile_image_url);
|
||||
}
|
||||
iconView.setBorderColor(account.color);
|
||||
iconView.setTag(account.profile_image_url);
|
||||
nameView.setText(adapter.isNameFirst() ? account.name : ("@" + account.screen_name));
|
||||
}
|
||||
|
||||
|
@ -1366,7 +1381,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
}
|
||||
|
||||
private static class AccountIconsAdapter extends BaseRecyclerViewAdapter<AccountIconViewHolder> {
|
||||
static class AccountIconsAdapter extends BaseRecyclerViewAdapter<AccountIconViewHolder> {
|
||||
|
||||
private final ComposeActivity mActivity;
|
||||
private final LayoutInflater mInflater;
|
||||
|
@ -1388,6 +1403,11 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
return mMediaLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return mAccounts[position].account_id;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public long[] getSelectedAccountIds() {
|
||||
if (mAccounts == null) return new long[0];
|
||||
|
@ -1468,9 +1488,9 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
}
|
||||
}
|
||||
|
||||
private static class AddBitmapTask extends AddMediaTask {
|
||||
static class AddBitmapTask extends AddMediaTask {
|
||||
|
||||
private final Bitmap mBitmap;
|
||||
final Bitmap mBitmap;
|
||||
|
||||
AddBitmapTask(ComposeActivity activity, Bitmap bitmap, Uri dst, int media_type) throws IOException {
|
||||
super(activity, Uri.fromFile(File.createTempFile("tmp_bitmap", null)), dst, media_type,
|
||||
|
@ -1496,24 +1516,26 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
}
|
||||
|
||||
private static class AddMediaTask extends AsyncTask<Object, Object, Boolean> {
|
||||
static class AddMediaTask extends AsyncTask<Object, Object, Boolean> {
|
||||
|
||||
private final ComposeActivity activity;
|
||||
private final int media_type;
|
||||
private final Uri src, dst;
|
||||
private final boolean delete_src;
|
||||
final WeakReference<ComposeActivity> mActivityRef;
|
||||
final int mMediaType;
|
||||
final Uri src, dst;
|
||||
final boolean mDeleteSrc;
|
||||
|
||||
AddMediaTask(final ComposeActivity activity, final Uri src, final Uri dst, final int media_type,
|
||||
final boolean delete_src) {
|
||||
this.activity = activity;
|
||||
AddMediaTask(final ComposeActivity activity, final Uri src, final Uri dst, final int mediaType,
|
||||
final boolean deleteSrc) {
|
||||
this.mActivityRef = new WeakReference<>(activity);
|
||||
this.src = src;
|
||||
this.dst = dst;
|
||||
this.media_type = media_type;
|
||||
this.delete_src = delete_src;
|
||||
this.mMediaType = mediaType;
|
||||
this.mDeleteSrc = deleteSrc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(final Object... params) {
|
||||
final ComposeActivity activity = this.mActivityRef.get();
|
||||
if (activity == null) return false;
|
||||
InputStream is = null;
|
||||
OutputStream os = null;
|
||||
try {
|
||||
|
@ -1521,7 +1543,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
is = resolver.openInputStream(src);
|
||||
os = resolver.openOutputStream(dst);
|
||||
Utils.copyStream(is, os);
|
||||
if (ContentResolver.SCHEME_FILE.equals(src.getScheme()) && delete_src) {
|
||||
if (ContentResolver.SCHEME_FILE.equals(src.getScheme()) && mDeleteSrc) {
|
||||
final File file = new File(src.getPath());
|
||||
if (!file.delete()) {
|
||||
Log.d(LOGTAG, String.format("Unable to delete %s", file));
|
||||
|
@ -1543,8 +1565,10 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(final Boolean result) {
|
||||
final ComposeActivity activity = mActivityRef.get();
|
||||
if (activity == null) return;
|
||||
activity.setProgressVisible(false);
|
||||
activity.addMedia(new ParcelableMediaUpdate(dst.toString(), media_type));
|
||||
activity.addMedia(new ParcelableMediaUpdate(dst.toString(), mMediaType));
|
||||
activity.setMenu();
|
||||
activity.updateTextCount();
|
||||
if (!result) {
|
||||
|
@ -1554,17 +1578,19 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
final ComposeActivity activity = mActivityRef.get();
|
||||
if (activity == null) return;
|
||||
activity.setProgressVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeleteImageTask extends AsyncTask<Object, Object, Boolean> {
|
||||
static class DeleteMediaTask extends AsyncTask<Object, Object, Boolean> {
|
||||
|
||||
final ComposeActivity mActivity;
|
||||
private final ParcelableMediaUpdate[] mMedia;
|
||||
final WeakReference<ComposeActivity> mActivity;
|
||||
final ParcelableMediaUpdate[] mMedia;
|
||||
|
||||
DeleteImageTask(final ComposeActivity activity, final ParcelableMediaUpdate... media) {
|
||||
this.mActivity = activity;
|
||||
DeleteMediaTask(final ComposeActivity activity, final ParcelableMediaUpdate... media) {
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.mMedia = media;
|
||||
}
|
||||
|
||||
|
@ -1589,31 +1615,37 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(final Boolean result) {
|
||||
mActivity.setProgressVisible(false);
|
||||
mActivity.removeAllMedia(Arrays.asList(mMedia));
|
||||
mActivity.setMenu();
|
||||
final ComposeActivity activity = mActivity.get();
|
||||
if (activity == null) return;
|
||||
activity.setProgressVisible(false);
|
||||
activity.removeAllMedia(Arrays.asList(mMedia));
|
||||
activity.setMenu();
|
||||
if (!result) {
|
||||
Toast.makeText(mActivity, R.string.error_occurred, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(activity, R.string.error_occurred, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
mActivity.setProgressVisible(true);
|
||||
final ComposeActivity activity = mActivity.get();
|
||||
if (activity == null) return;
|
||||
activity.setProgressVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DiscardTweetTask extends AsyncTask<Object, Object, Object> {
|
||||
static class DiscardTweetTask extends AsyncTask<Object, Object, Object> {
|
||||
|
||||
final ComposeActivity mActivity;
|
||||
final WeakReference<ComposeActivity> mActivity;
|
||||
|
||||
DiscardTweetTask(final ComposeActivity activity) {
|
||||
this.mActivity = activity;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doInBackground(final Object... params) {
|
||||
for (final ParcelableMediaUpdate media : mActivity.getMediaList()) {
|
||||
final ComposeActivity activity = mActivity.get();
|
||||
if (activity == null) return null;
|
||||
for (final ParcelableMediaUpdate media : activity.getMediaList()) {
|
||||
final Uri uri = Uri.parse(media.uri);
|
||||
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
|
||||
final File file = new File(uri.getPath());
|
||||
|
@ -1627,27 +1659,31 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(final Object result) {
|
||||
mActivity.setProgressVisible(false);
|
||||
mActivity.finish();
|
||||
final ComposeActivity activity = mActivity.get();
|
||||
if (activity == null) return;
|
||||
activity.setProgressVisible(false);
|
||||
activity.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
mActivity.setProgressVisible(true);
|
||||
final ComposeActivity activity = mActivity.get();
|
||||
if (activity == null) return;
|
||||
activity.setProgressVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MediaPreviewAdapter extends ArrayRecyclerAdapter<ParcelableMediaUpdate, MediaPreviewViewHolder>
|
||||
implements SimpleItemTouchHelperCallback.ItemTouchHelperAdapter {
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
final LayoutInflater mInflater;
|
||||
|
||||
private final SimpleItemTouchHelperCallback.OnStartDragListener mDragStartListener;
|
||||
final SimpleItemTouchHelperCallback.OnStartDragListener mDragStartListener;
|
||||
|
||||
public MediaPreviewAdapter(final ComposeActivity activity, SimpleItemTouchHelperCallback.OnStartDragListener dragStartListener) {
|
||||
public MediaPreviewAdapter(final ComposeActivity activity, SimpleItemTouchHelperCallback.OnStartDragListener listener) {
|
||||
super(activity);
|
||||
mInflater = LayoutInflater.from(activity);
|
||||
mDragStartListener = dragStartListener;
|
||||
mDragStartListener = listener;
|
||||
}
|
||||
|
||||
public void onStartDrag(ViewHolder viewHolder) {
|
||||
|
@ -1668,7 +1704,19 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
@Override
|
||||
public MediaPreviewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
final View view = mInflater.inflate(R.layout.grid_item_media_editor, parent, false);
|
||||
return new MediaPreviewViewHolder(this, view);
|
||||
return new MediaPreviewViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(MediaPreviewViewHolder holder) {
|
||||
super.onViewAttachedToWindow(holder);
|
||||
holder.setAdapter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(MediaPreviewViewHolder holder) {
|
||||
holder.setAdapter(null);
|
||||
super.onViewDetachedFromWindow(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1689,12 +1737,11 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
static class MediaPreviewViewHolder extends ViewHolder implements OnLongClickListener {
|
||||
|
||||
private final ImageView image;
|
||||
private final MediaPreviewAdapter adapter;
|
||||
final ImageView image;
|
||||
MediaPreviewAdapter adapter;
|
||||
|
||||
public MediaPreviewViewHolder(MediaPreviewAdapter adapter, View itemView) {
|
||||
public MediaPreviewViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
this.adapter = adapter;
|
||||
itemView.setOnLongClickListener(this);
|
||||
image = (ImageView) itemView.findViewById(R.id.image);
|
||||
}
|
||||
|
@ -1705,10 +1752,15 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (adapter == null) return false;
|
||||
adapter.onStartDrag(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setAdapter(final MediaPreviewAdapter adapter) {
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class RetweetProtectedStatusWarnFragment extends BaseSupportDialogFragment implements
|
||||
|
@ -1740,9 +1792,9 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
|||
}
|
||||
}
|
||||
|
||||
private static class SpacingItemDecoration extends ItemDecoration {
|
||||
static class SpacingItemDecoration extends ItemDecoration {
|
||||
|
||||
private final int mSpacingSmall, mSpacingNormal;
|
||||
final int mSpacingSmall, mSpacingNormal;
|
||||
|
||||
SpacingItemDecoration(Context context) {
|
||||
final Resources resources = context.getResources();
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.mariotaku.twidere.BuildConfig;
|
|||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.activity.iface.IAppCompatActivity;
|
||||
import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
||||
import org.mariotaku.twidere.util.DebugModeUtils;
|
||||
import org.mariotaku.twidere.util.StrictModeUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.mariotaku.twidere.Constants;
|
|||
import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
||||
import org.mariotaku.twidere.util.ActivityTracker;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.DebugModeUtils;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
|
|
|
@ -75,5 +75,8 @@ public class ThemedImagePickerActivity extends ImagePickerActivity {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,11 +135,13 @@ public class EmojiSupportUtils {
|
|||
}
|
||||
|
||||
private static boolean isPhoneNumberSymbol(int codePoint) {
|
||||
return codePoint == 0x0023 || codePoint == 0x002a || TwidereMathUtils.inRangeInclusiveInclusive(codePoint, 0x0030, 0x0039);
|
||||
return codePoint == 0x0023 || codePoint == 0x002a || TwidereMathUtils.inRange(codePoint,
|
||||
0x0030, 0x0039, TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE);
|
||||
}
|
||||
|
||||
private static boolean isModifier(int codePoint) {
|
||||
return TwidereMathUtils.inRangeInclusiveInclusive(codePoint, 0x1f3fb, 0x1f3ff);
|
||||
return TwidereMathUtils.inRange(codePoint, 0x1f3fb, 0x1f3ff,
|
||||
TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE);
|
||||
}
|
||||
|
||||
private static boolean isEmoji(int codePoint) {
|
||||
|
@ -147,7 +149,8 @@ public class EmojiSupportUtils {
|
|||
}
|
||||
|
||||
private static boolean isRegionalIndicatorSymbol(int codePoint) {
|
||||
return TwidereMathUtils.inRangeInclusiveInclusive(codePoint, 0x1f1e6, 0x1f1ff);
|
||||
return TwidereMathUtils.inRange(codePoint, 0x1f1e6, 0x1f1ff,
|
||||
TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE);
|
||||
}
|
||||
|
||||
private static boolean isKeyCap(int codePoint) {
|
||||
|
|
|
@ -22,6 +22,13 @@ package org.mariotaku.twidere.util;
|
|||
import android.support.annotation.NonNull;
|
||||
|
||||
public class TwidereMathUtils {
|
||||
public static final int RANGE_EXCLUSIVE_EXCLUSIVE = 0b00;
|
||||
public static final int RANGE_EXCLUSIVE_INCLUSIVE = 0b01;
|
||||
public static final int RANGE_INCLUSIVE_EXCLUSIVE = 0b10;
|
||||
public static final int RANGE_INCLUSIVE_INCLUSIVE = 0b11;
|
||||
static final int MASK_LEFT_BOUND = 0b10;
|
||||
static final int MASK_RIGHT_BOUND = 0b01;
|
||||
|
||||
public static float clamp(final float num, final float bound1, final float bound2) {
|
||||
final float max = Math.max(bound1, bound2), min = Math.min(bound1, bound2);
|
||||
return Math.max(Math.min(num, max), min);
|
||||
|
@ -76,8 +83,14 @@ public class TwidereMathUtils {
|
|||
return sum;
|
||||
}
|
||||
|
||||
public static boolean inRangeInclusiveInclusive(int num, int from, int to) {
|
||||
return num >= from && num <= to;
|
||||
public static boolean inRange(int num, int from, int to, int flag) {
|
||||
return ((flag & MASK_LEFT_BOUND) == 0 ? num > from : num >= from)
|
||||
&& ((flag & MASK_RIGHT_BOUND) == 0 ? num < to : num <= to);
|
||||
}
|
||||
|
||||
public static boolean inRange(float num, float from, float to, int flag) {
|
||||
return ((flag & MASK_LEFT_BOUND) == 0 ? num > from : num >= from)
|
||||
&& ((flag & MASK_RIGHT_BOUND) == 0 ? num < to : num <= to);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/23.
|
||||
*/
|
||||
public class TwidereViewUtils {
|
||||
@UiThread
|
||||
public static boolean hitView(float x, float y, View view) {
|
||||
int[] location = new int[2];
|
||||
view.getLocationOnScreen(location);
|
||||
return TwidereMathUtils.inRange(x, location[0], location[0] + view.getWidth(), TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE) &&
|
||||
TwidereMathUtils.inRange(x, location[1], location[1] + view.getHeight(), TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE);
|
||||
}
|
||||
}
|
|
@ -178,7 +178,8 @@ public class TwitterAPIFactory implements TwidereConstants {
|
|||
final String proxyType = prefs.getString(KEY_PROXY_TYPE, null);
|
||||
final String proxyHost = prefs.getString(KEY_PROXY_HOST, null);
|
||||
final int proxyPort = NumberUtils.toInt(prefs.getString(KEY_PROXY_PORT, null), -1);
|
||||
if (!isEmpty(proxyHost) && TwidereMathUtils.inRangeInclusiveInclusive(proxyPort, 0, 65535)) {
|
||||
if (!isEmpty(proxyHost) && TwidereMathUtils.inRange(proxyPort, 0, 65535,
|
||||
TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE)) {
|
||||
client.setProxy(null);
|
||||
client.setProxySelector(new TwidereProxySelector(context, getProxyType(proxyType),
|
||||
proxyHost, proxyPort));
|
||||
|
@ -213,7 +214,8 @@ public class TwitterAPIFactory implements TwidereConstants {
|
|||
final String proxyType = prefs.getString(KEY_PROXY_TYPE, null);
|
||||
final String proxyHost = prefs.getString(KEY_PROXY_HOST, null);
|
||||
final int proxyPort = NumberUtils.toInt(prefs.getString(KEY_PROXY_PORT, null), -1);
|
||||
if (!isEmpty(proxyHost) && TwidereMathUtils.inRangeInclusiveInclusive(proxyPort, 0, 65535)) {
|
||||
if (!isEmpty(proxyHost) && TwidereMathUtils.inRange(proxyPort, 0, 65535,
|
||||
TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE)) {
|
||||
final SocketAddress addr = InetSocketAddress.createUnresolved(proxyHost, proxyPort);
|
||||
return new Proxy(getProxyType(proxyType), addr);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<LinearLayout
|
||||
android:id="@+id/compose_activity"
|
||||
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="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="@dimen/compose_min_width"
|
||||
|
@ -49,14 +51,14 @@
|
|||
android:minLines="6"
|
||||
android:padding="@dimen/element_spacing_normal"
|
||||
android:scrollbars="vertical"
|
||||
android:singleLine="false" />
|
||||
android:singleLine="false"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/attached_media_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="128dp"
|
||||
android:layout_weight="0"
|
||||
tools:listitem="@layout/grid_item_media_editor" />
|
||||
tools:listitem="@layout/grid_item_media_editor"/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
|
@ -77,14 +79,14 @@
|
|||
android:layout_marginLeft="@dimen/element_spacing_normal"
|
||||
android:layout_marginRight="@dimen/element_spacing_normal"
|
||||
android:color="?android:textColorSecondary"
|
||||
android:src="@drawable/ic_action_location" />
|
||||
android:src="@drawable/ic_action_location"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:id="@+id/location_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/element_spacing_normal"
|
||||
android:layout_marginRight="@dimen/element_spacing_normal" />
|
||||
android:layout_marginRight="@dimen/element_spacing_normal"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -107,21 +109,122 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:overScrollMode="never" />
|
||||
android:overScrollMode="never"/>
|
||||
</FrameLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?dividerVertical"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/compose_bottombar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:background="?android:panelColorBackground"
|
||||
android:divider="?android:dividerVertical"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="beginning">
|
||||
android:baselineAligned="false">
|
||||
|
||||
<include layout="@layout/activity_compose_bottombar" />
|
||||
</LinearLayout>
|
||||
<RelativeLayout
|
||||
android:id="@+id/account_selector_button"
|
||||
style="?actionButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:clickable="true"
|
||||
android:paddingBottom="@dimen/element_spacing_msmall"
|
||||
android:paddingEnd="@dimen/element_spacing_msmall"
|
||||
android:paddingLeft="@dimen/element_spacing_msmall"
|
||||
android:paddingRight="@dimen/element_spacing_msmall"
|
||||
android:paddingStart="@dimen/element_spacing_msmall"
|
||||
android:paddingTop="@dimen/element_spacing_msmall">
|
||||
|
||||
<org.mariotaku.twidere.view.SquareFrameLayout
|
||||
android:id="@+id/account_profile_image_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@+id/account_profile_image"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
app:sivBackgroundColor="?android:colorBackground"
|
||||
app:sivBorder="true"
|
||||
app:sivBorderWidth="@dimen/line_width_compose_account_profile_image"/>
|
||||
</org.mariotaku.twidere.view.SquareFrameLayout>
|
||||
|
||||
<org.mariotaku.twidere.view.BadgeView
|
||||
android:id="@+id/accounts_count"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignBottom="@id/account_profile_image_frame"
|
||||
android:layout_alignEnd="@id/account_profile_image_frame"
|
||||
android:layout_alignLeft="@id/account_profile_image_frame"
|
||||
android:layout_alignRight="@id/account_profile_image_frame"
|
||||
android:layout_alignStart="@id/account_profile_image_frame"
|
||||
android:layout_alignTop="@id/account_profile_image_frame"
|
||||
android:layout_gravity="center"
|
||||
android:textColor="?android:colorForeground"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toEndOf="@+id/account_selector_button"
|
||||
android:layout_toLeftOf="@+id/send"
|
||||
android:layout_toRightOf="@+id/account_selector_button"
|
||||
android:layout_toStartOf="@+id/send"
|
||||
android:scrollbars="none">
|
||||
|
||||
<android.support.v7.widget.ActionMenuView
|
||||
android:id="@+id/menu_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:background="@null"/>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/send"
|
||||
style="?actionButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:contentDescription="@string/send"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="@dimen/element_spacing_normal"
|
||||
android:paddingEnd="@dimen/element_spacing_normal"
|
||||
android:paddingLeft="@dimen/element_spacing_large"
|
||||
android:paddingRight="@dimen/element_spacing_normal"
|
||||
android:paddingStart="@dimen/element_spacing_large"
|
||||
android:paddingTop="@dimen/element_spacing_normal">
|
||||
|
||||
<org.mariotaku.twidere.view.StatusTextCountView
|
||||
android:id="@+id/status_text_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:minWidth="@dimen/element_size_small"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
tools:text="140"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:color="?android:textColorSecondary"
|
||||
android:contentDescription="@string/send"
|
||||
android:cropToPadding="false"
|
||||
android:padding="@dimen/element_spacing_xsmall"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_action_send"/>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
|
@ -30,9 +30,8 @@
|
|||
<org.mariotaku.twidere.view.ShapedImageView
|
||||
android:id="@android:id/icon"
|
||||
style="?profileImageStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="@dimen/element_size_normal"
|
||||
android:layout_width="@dimen/element_size_normal"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
app:sivBorder="true"
|
||||
app:sivBorderWidth="@dimen/line_width_compose_account_profile_image"
|
||||
app:sivElevation="@dimen/elevation_card"/>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
<style name="Widget.ProfileImage" parent="Widget.Base">
|
||||
<item name="android:scaleType">centerCrop</item>
|
||||
<item name="android:adjustViewBounds">false</item>
|
||||
<item name="sivBorderWidth">1dp</item>
|
||||
<item name="sivCornerRadiusRatio">10%p</item>
|
||||
<item name="sivBackgroundColor">?android:colorBackground</item>
|
||||
|
@ -38,6 +39,7 @@
|
|||
|
||||
<style name="Widget.Light.ProfileImage" parent="Widget.Base">
|
||||
<item name="android:scaleType">centerCrop</item>
|
||||
<item name="android:adjustViewBounds">false</item>
|
||||
<item name="sivBorderWidth">1dp</item>
|
||||
<item name="sivCornerRadiusRatio">10%p</item>
|
||||
<item name="sivBackgroundColor">?android:colorBackground</item>
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package org.mariotaku.twidere.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/23.
|
||||
*/
|
||||
public class TwidereMathUtilsTest {
|
||||
|
||||
public void testClamp() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
public void testClamp1() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
public void testNextPowerOf2() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
public void testPrevPowerOf2() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
public void testSum() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
public void testSum1() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
public void testSum2() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInRange() {
|
||||
assertTrue(TwidereMathUtils.inRange(5, 0, 10, TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(0, 0, 10, TwidereMathUtils.RANGE_EXCLUSIVE_EXCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(0, 5, 10, TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(5, 5, 10, TwidereMathUtils.RANGE_EXCLUSIVE_INCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(10, 5, 10, TwidereMathUtils.RANGE_INCLUSIVE_EXCLUSIVE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInRange1() {
|
||||
assertTrue(TwidereMathUtils.inRange(5f, 0f, 10f, TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(0f, 0f, 10f, TwidereMathUtils.RANGE_EXCLUSIVE_EXCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(0f, 5f, 10f, TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(5f, 5f, 10f, TwidereMathUtils.RANGE_EXCLUSIVE_INCLUSIVE));
|
||||
assertFalse(TwidereMathUtils.inRange(10f, 5f, 10f, TwidereMathUtils.RANGE_INCLUSIVE_EXCLUSIVE));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue