improved compose dialog

This commit is contained in:
Mariotaku Lee 2016-01-23 16:24:38 +08:00
parent b92bf74781
commit e988f54448
15 changed files with 375 additions and 158 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -75,5 +75,8 @@ public class ThemedImagePickerActivity extends ImagePickerActivity {
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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