make profile page works temporarily

removed some unused preferences
moved account actions to accounts screen
This commit is contained in:
Mariotaku Lee 2014-11-14 12:16:46 +08:00
parent f1db4e6ca7
commit caa57c848b
34 changed files with 1399 additions and 1311 deletions

View File

@ -82,6 +82,7 @@ dependencies {
compile 'com.android.support:support-v13:21.0.0' compile 'com.android.support:support-v13:21.0.0'
compile 'com.android.support:cardview-v7:21.0.0' compile 'com.android.support:cardview-v7:21.0.0'
compile 'com.android.support:recyclerview-v7:21.0.0' compile 'com.android.support:recyclerview-v7:21.0.0'
compile 'com.android.support:palette-v7:21.0.0'
compile 'com.etsy.android.grid:library:1.0.5' compile 'com.etsy.android.grid:library:1.0.5'
compile 'com.sothree.slidinguppanel:library:2.0.0' compile 'com.sothree.slidinguppanel:library:2.0.0'
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5' compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'

View File

@ -136,6 +136,7 @@ public class AccountSelectorActivity extends BaseSupportDialogActivity implement
final boolean isSingleSelection = isSingleSelection(); final boolean isSingleSelection = isSingleSelection();
mListView.setChoiceMode(isSingleSelection ? ListView.CHOICE_MODE_NONE : ListView.CHOICE_MODE_MULTIPLE); mListView.setChoiceMode(isSingleSelection ? ListView.CHOICE_MODE_NONE : ListView.CHOICE_MODE_MULTIPLE);
mAdapter.setChoiceMode(mListView.getChoiceMode()); mAdapter.setChoiceMode(mListView.getChoiceMode());
mAdapter.setSortEnabled(false);
if (isSingleSelection) { if (isSingleSelection) {
mListView.setOnItemClickListener(this); mListView.setOnItemClickListener(this);
} }

View File

@ -31,6 +31,8 @@ import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.graphics.Palette;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.Menu; import android.view.Menu;
@ -40,7 +42,6 @@ import android.view.View.OnClickListener;
import android.view.Window; import android.view.Window;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
@ -49,7 +50,6 @@ import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.support.BaseSupportDialogFragment; import org.mariotaku.twidere.fragment.support.BaseSupportDialogFragment;
import org.mariotaku.twidere.provider.TweetStore.Accounts; import org.mariotaku.twidere.provider.TweetStore.Accounts;
import org.mariotaku.twidere.task.AsyncTask; import org.mariotaku.twidere.task.AsyncTask;
import org.mariotaku.twidere.util.ColorAnalyser;
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator;
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticationException; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticationException;
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticityTokenException; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticityTokenException;
@ -59,7 +59,6 @@ import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.net.TwidereHostResolverFactory; import org.mariotaku.twidere.util.net.TwidereHostResolverFactory;
import org.mariotaku.twidere.util.net.TwidereHttpClientFactory; import org.mariotaku.twidere.util.net.TwidereHttpClientFactory;
import org.mariotaku.twidere.view.ColorPickerView;
import de.keyboardsurfer.android.widget.crouton.Crouton; import de.keyboardsurfer.android.widget.crouton.Crouton;
import de.keyboardsurfer.android.widget.crouton.CroutonLifecycleCallback; import de.keyboardsurfer.android.widget.crouton.CroutonLifecycleCallback;
@ -98,15 +97,12 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
private int mAuthType; private int mAuthType;
private String mConsumerKey, mConsumerSecret; private String mConsumerKey, mConsumerSecret;
private String mUsername, mPassword; private String mUsername, mPassword;
private Integer mUserColor;
private long mLoggedId;
private boolean mBackPressed; private boolean mBackPressed;
private long mAPIChangeTimestamp; private long mAPIChangeTimestamp;
private EditText mEditUsername, mEditPassword; private EditText mEditUsername, mEditPassword;
private Button mSignInButton, mSignUpButton; private Button mSignInButton, mSignUpButton;
private LinearLayout mSigninSignupContainer, mUsernamePasswordContainer; private LinearLayout mSigninSignupContainer, mUsernamePasswordContainer;
private ImageButton mSetColorButton;
private TwidereApplication mApplication; private TwidereApplication mApplication;
private SharedPreferences mPreferences; private SharedPreferences mPreferences;
@ -144,15 +140,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
invalidateOptionsMenu(); invalidateOptionsMenu();
break; break;
} }
case REQUEST_SET_COLOR: {
if (resultCode == BaseSupportActivity.RESULT_OK) {
mUserColor = data != null ? data.getIntExtra(EXTRA_COLOR, Color.TRANSPARENT) : null;
} else if (resultCode == ColorPickerDialogActivity.RESULT_CLEARED) {
mUserColor = null;
}
setUserColorButton();
break;
}
case REQUEST_BROWSER_SIGN_IN: { case REQUEST_BROWSER_SIGN_IN: {
if (resultCode == BaseSupportActivity.RESULT_OK && data != null) { if (resultCode == BaseSupportActivity.RESULT_OK && data != null) {
doLogin(data); doLogin(data);
@ -190,16 +177,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
doLogin(); doLogin();
break; break;
} }
case R.id.set_color: {
final Intent intent = new Intent(this, ColorPickerDialogActivity.class);
if (mUserColor != null) {
intent.putExtra(EXTRA_COLOR, mUserColor);
}
intent.putExtra(EXTRA_ALPHA_SLIDER, false);
intent.putExtra(EXTRA_CLEAR_BUTTON, true);
startActivityForResult(intent, REQUEST_SET_COLOR);
break;
}
case R.id.sign_in_method_introduction: { case R.id.sign_in_method_introduction: {
new SignInMethodIntroductionDialogFragment().show(getSupportFragmentManager(), new SignInMethodIntroductionDialogFragment().show(getSupportFragmentManager(),
"sign_in_method_introduction"); "sign_in_method_introduction");
@ -217,7 +194,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mSignUpButton = (Button) findViewById(R.id.sign_up); mSignUpButton = (Button) findViewById(R.id.sign_up);
mSigninSignupContainer = (LinearLayout) findViewById(R.id.sign_in_sign_up); mSigninSignupContainer = (LinearLayout) findViewById(R.id.sign_in_sign_up);
mUsernamePasswordContainer = (LinearLayout) findViewById(R.id.username_password); mUsernamePasswordContainer = (LinearLayout) findViewById(R.id.username_password);
mSetColorButton = (ImageButton) findViewById(R.id.set_color);
} }
@Override @Override
@ -309,9 +285,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
outState.putString(Accounts.SCREEN_NAME, mUsername); outState.putString(Accounts.SCREEN_NAME, mUsername);
outState.putString(Accounts.PASSWORD, mPassword); outState.putString(Accounts.PASSWORD, mPassword);
outState.putLong(EXTRA_API_LAST_CHANGE, mAPIChangeTimestamp); outState.putLong(EXTRA_API_LAST_CHANGE, mAPIChangeTimestamp);
if (mUserColor != null) {
outState.putInt(Accounts.COLOR, mUserColor);
}
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@ -340,9 +313,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mConsumerSecret = trim(savedInstanceState.getString(Accounts.CONSUMER_SECRET)); mConsumerSecret = trim(savedInstanceState.getString(Accounts.CONSUMER_SECRET));
mUsername = savedInstanceState.getString(Accounts.SCREEN_NAME); mUsername = savedInstanceState.getString(Accounts.SCREEN_NAME);
mPassword = savedInstanceState.getString(Accounts.PASSWORD); mPassword = savedInstanceState.getString(Accounts.PASSWORD);
if (savedInstanceState.containsKey(Accounts.COLOR)) {
mUserColor = savedInstanceState.getInt(Accounts.COLOR, Color.TRANSPARENT);
}
mAPIChangeTimestamp = savedInstanceState.getLong(EXTRA_API_LAST_CHANGE); mAPIChangeTimestamp = savedInstanceState.getLong(EXTRA_API_LAST_CHANGE);
} }
@ -356,7 +326,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mEditPassword.setText(mPassword); mEditPassword.setText(mPassword);
mEditPassword.addTextChangedListener(this); mEditPassword.addTextChangedListener(this);
setSignInButton(); setSignInButton();
setUserColorButton();
} }
private void doLogin() { private void doLogin() {
@ -366,7 +335,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
saveEditedText(); saveEditedText();
setDefaultAPI(); setDefaultAPI();
final Configuration conf = getConfiguration(); final Configuration conf = getConfiguration();
mTask = new SignInTask(this, conf, mUsername, mPassword, mAuthType, mUserColor, mAPIUrlFormat, mTask = new SignInTask(this, conf, mUsername, mPassword, mAuthType, mAPIUrlFormat,
mSameOAuthSigningUrl, mNoVersionSuffix); mSameOAuthSigningUrl, mNoVersionSuffix);
mTask.execute(); mTask.execute();
} }
@ -382,7 +351,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
final String token = intent.getStringExtra(EXTRA_REQUEST_TOKEN); final String token = intent.getStringExtra(EXTRA_REQUEST_TOKEN);
final String secret = intent.getStringExtra(EXTRA_REQUEST_TOKEN_SECRET); final String secret = intent.getStringExtra(EXTRA_REQUEST_TOKEN_SECRET);
final String verifier = intent.getStringExtra(EXTRA_OAUTH_VERIFIER); final String verifier = intent.getStringExtra(EXTRA_OAUTH_VERIFIER);
mTask = new BrowserSignInTask(this, conf, token, secret, verifier, mUserColor, mAPIUrlFormat, mTask = new BrowserSignInTask(this, conf, token, secret, verifier, mAPIUrlFormat,
mSameOAuthSigningUrl, mNoVersionSuffix); mSameOAuthSigningUrl, mNoVersionSuffix);
mTask.execute(); mTask.execute();
} }
@ -472,14 +441,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
|| mAuthType == Accounts.AUTH_TYPE_TWIP_O_MODE); || mAuthType == Accounts.AUTH_TYPE_TWIP_O_MODE);
} }
private void setUserColorButton() {
if (mUserColor != null) {
mSetColorButton.setImageBitmap(ColorPickerView.getColorPreviewBitmap(this, mUserColor));
} else {
mSetColorButton.setImageResource(R.drawable.ic_action_color_palette);
}
}
void onSignInResult(final SignInResponse result) { void onSignInResult(final SignInResponse result) {
if (result != null) { if (result != null) {
if (result.succeed) { if (result.succeed) {
@ -510,10 +471,10 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
if (values != null) { if (values != null) {
mResolver.insert(Accounts.CONTENT_URI, values); mResolver.insert(Accounts.CONTENT_URI, values);
} }
mLoggedId = result.user.getId(); final long loggedId = result.user.getId();
final Intent intent = new Intent(this, HomeActivity.class); final Intent intent = new Intent(this, HomeActivity.class);
final Bundle bundle = new Bundle(); final Bundle bundle = new Bundle();
bundle.putLongArray(EXTRA_IDS, new long[]{mLoggedId}); bundle.putLongArray(EXTRA_IDS, new long[]{loggedId});
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent); startActivity(intent);
@ -537,7 +498,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mEditUsername.setEnabled(true); mEditUsername.setEnabled(true);
mSignInButton.setEnabled(true); mSignInButton.setEnabled(true);
mSignUpButton.setEnabled(true); mSignUpButton.setEnabled(true);
mSetColorButton.setEnabled(true);
setSignInButton(); setSignInButton();
} }
@ -547,7 +507,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mEditUsername.setEnabled(false); mEditUsername.setEnabled(false);
mSignInButton.setEnabled(false); mSignInButton.setEnabled(false);
mSignUpButton.setEnabled(false); mSignUpButton.setEnabled(false);
mSetColorButton.setEnabled(false);
} }
public static abstract class AbstractSignInTask extends AsyncTask<Void, Void, SignInResponse> { public static abstract class AbstractSignInTask extends AsyncTask<Void, Void, SignInResponse> {
@ -574,24 +533,25 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
} }
} }
int getProfileBackgroundColor(String color) {
if (isEmpty(color)) return Color.TRANSPARENT;
try {
return Color.parseColor(color);
} catch (IllegalArgumentException e) {
return Color.TRANSPARENT;
}
}
int analyseUserProfileColor(final User user) throws TwitterException { int analyseUserProfileColor(final User user) throws TwitterException {
if (user == null) throw new TwitterException("Unable to get user info"); if (user == null) throw new TwitterException("Unable to get user info");
final HttpClientWrapper client = new HttpClientWrapper(conf); final HttpClientWrapper client = new HttpClientWrapper(conf);
final String profileImageUrl = ParseUtils.parseString(user.getProfileImageURL()); final String profileImageUrl = ParseUtils.parseString(user.getProfileImageURL());
final HttpResponse conn = profileImageUrl != null ? client.get(profileImageUrl, null) : null; final HttpResponse conn = profileImageUrl != null ? client.get(profileImageUrl, null) : null;
final Bitmap bm = conn != null ? BitmapFactory.decodeStream(conn.asStream()) : null; final Bitmap bm = conn != null ? BitmapFactory.decodeStream(conn.asStream()) : null;
if (bm == null) { final int profileBackgroundColor = getProfileBackgroundColor(user.getProfileBackgroundColor());
if (bm == null) return profileBackgroundColor;
try { try {
final String profileBackgroundColor = user.getProfileBackgroundColor(); return Palette.generate(bm).getVibrantColor(profileBackgroundColor);
if (isEmpty(profileBackgroundColor))
throw new TwitterException("Can't get profile image");
return Color.parseColor(profileBackgroundColor);
} catch (final IllegalArgumentException e) {
throw new TwitterException("Can't get profile image");
}
}
try {
return ColorAnalyser.analyse(bm);
} finally { } finally {
bm.recycle(); bm.recycle();
} }
@ -603,22 +563,21 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
private final Configuration conf; private final Configuration conf;
private final String request_token, request_token_secret, oauth_verifier; private final String request_token, request_token_secret, oauth_verifier;
private final Integer user_color;
private final Context context; private final Context context;
private final String api_url_format; private final String api_url_format;
private final boolean same_oauth_signing_url, no_version_suffix; private final boolean same_oauth_signing_url, no_version_suffix;
public BrowserSignInTask(final SignInActivity context, final Configuration conf, final String request_token, public BrowserSignInTask(final SignInActivity context, final Configuration conf,
final String request_token_secret, final String oauth_verifier, final Integer user_color, final String request_token, final String request_token_secret,
final String api_url_format, final boolean same_oauth_signing_url, final boolean no_version_suffix) { final String oauth_verifier, final String api_url_format,
final boolean same_oauth_signing_url, final boolean no_version_suffix) {
super(context, conf); super(context, conf);
this.context = context; this.context = context;
this.conf = conf; this.conf = conf;
this.request_token = request_token; this.request_token = request_token;
this.request_token_secret = request_token_secret; this.request_token_secret = request_token_secret;
this.oauth_verifier = oauth_verifier; this.oauth_verifier = oauth_verifier;
this.user_color = user_color;
this.api_url_format = api_url_format; this.api_url_format = api_url_format;
this.same_oauth_signing_url = same_oauth_signing_url; this.same_oauth_signing_url = same_oauth_signing_url;
this.no_version_suffix = no_version_suffix; this.no_version_suffix = no_version_suffix;
@ -634,7 +593,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
if (userId <= 0) return new SignInResponse(false, false, null); if (userId <= 0) return new SignInResponse(false, false, null);
final User user = twitter.verifyCredentials(); final User user = twitter.verifyCredentials();
if (isUserLoggedIn(context, userId)) return new SignInResponse(true, false, null); if (isUserLoggedIn(context, userId)) return new SignInResponse(true, false, null);
final int color = user_color != null ? user_color : analyseUserProfileColor(user); final int color = analyseUserProfileColor(user);
return new SignInResponse(conf, access_token, user, Accounts.AUTH_TYPE_OAUTH, color, return new SignInResponse(conf, access_token, user, Accounts.AUTH_TYPE_OAUTH, color,
api_url_format, same_oauth_signing_url, no_version_suffix); api_url_format, same_oauth_signing_url, no_version_suffix);
} catch (final TwitterException e) { } catch (final TwitterException e) {
@ -645,6 +604,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
public static class SignInMethodIntroductionDialogFragment extends BaseSupportDialogFragment { public static class SignInMethodIntroductionDialogFragment extends BaseSupportDialogFragment {
@NonNull
@Override @Override
public Dialog onCreateDialog(final Bundle savedInstanceState) { public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity()); final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
@ -662,22 +622,21 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
private final Configuration conf; private final Configuration conf;
private final String username, password; private final String username, password;
private final int auth_type; private final int auth_type;
private final Integer user_color;
private final Context context; private final Context context;
private final String api_url_format; private final String api_url_format;
private final boolean same_oauth_signing_url, no_version_suffix; private final boolean same_oauth_signing_url, no_version_suffix;
public SignInTask(final SignInActivity context, final Configuration conf, final String username, public SignInTask(final SignInActivity context, final Configuration conf,
final String password, final int auth_type, final Integer user_color, final String api_url_format, final String username, final String password, final int auth_type,
final boolean same_oauth_signing_url, final boolean no_version_suffix) { final String api_url_format, final boolean same_oauth_signing_url,
final boolean no_version_suffix) {
super(context, conf); super(context, conf);
this.context = context; this.context = context;
this.conf = conf; this.conf = conf;
this.username = username; this.username = username;
this.password = password; this.password = password;
this.auth_type = auth_type; this.auth_type = auth_type;
this.user_color = user_color;
this.api_url_format = api_url_format; this.api_url_format = api_url_format;
this.same_oauth_signing_url = same_oauth_signing_url; this.same_oauth_signing_url = same_oauth_signing_url;
this.no_version_suffix = no_version_suffix; this.no_version_suffix = no_version_suffix;
@ -712,7 +671,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
final long user_id = user.getId(); final long user_id = user.getId();
if (user_id <= 0) return new SignInResponse(false, false, null); if (user_id <= 0) return new SignInResponse(false, false, null);
if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null); if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null);
final int color = user_color != null ? user_color : analyseUserProfileColor(user); final int color = analyseUserProfileColor(user);
return new SignInResponse(conf, username, password, user, color, api_url_format, return new SignInResponse(conf, username, password, user, color, api_url_format,
no_version_suffix); no_version_suffix);
} }
@ -725,7 +684,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
if (user_id <= 0) return new SignInResponse(false, false, null); if (user_id <= 0) return new SignInResponse(false, false, null);
final User user = twitter.verifyCredentials(); final User user = twitter.verifyCredentials();
if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null); if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null);
final int color = user_color != null ? user_color : analyseUserProfileColor(user); final int color = analyseUserProfileColor(user);
return new SignInResponse(conf, access_token, user, Accounts.AUTH_TYPE_OAUTH, color, return new SignInResponse(conf, access_token, user, Accounts.AUTH_TYPE_OAUTH, color,
api_url_format, same_oauth_signing_url, no_version_suffix); api_url_format, same_oauth_signing_url, no_version_suffix);
} }
@ -736,7 +695,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
final long user_id = user.getId(); final long user_id = user.getId();
if (user_id <= 0) return new SignInResponse(false, false, null); if (user_id <= 0) return new SignInResponse(false, false, null);
if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null); if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null);
final int color = user_color != null ? user_color : analyseUserProfileColor(user); final int color = analyseUserProfileColor(user);
return new SignInResponse(conf, user, color, api_url_format, no_version_suffix); return new SignInResponse(conf, user, color, api_url_format, no_version_suffix);
} }
@ -747,7 +706,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
final long user_id = user.getId(); final long user_id = user.getId();
if (user_id <= 0) return new SignInResponse(false, false, null); if (user_id <= 0) return new SignInResponse(false, false, null);
if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null); if (isUserLoggedIn(context, user_id)) return new SignInResponse(true, false, null);
final int color = user_color != null ? user_color : analyseUserProfileColor(user); final int color = analyseUserProfileColor(user);
return new SignInResponse(conf, access_token, user, Accounts.AUTH_TYPE_XAUTH, color, return new SignInResponse(conf, access_token, user, Accounts.AUTH_TYPE_XAUTH, color,
api_url_format, same_oauth_signing_url, no_version_suffix); api_url_format, same_oauth_signing_url, no_version_suffix);
} }
@ -759,12 +718,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
return ThemeUtils.getSettingsThemeResource(this); return ThemeUtils.getSettingsThemeResource(this);
} }
static interface SigninCallback {
void onSigninResult(SignInResponse response);
void onSigninStart();
}
static class SignInResponse { static class SignInResponse {
public final boolean already_logged_in, succeed; public final boolean already_logged_in, succeed;

View File

@ -32,6 +32,8 @@ import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IBaseAdapter; import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.Account;
import org.mariotaku.twidere.model.Account.Indices;
import org.mariotaku.twidere.provider.TweetStore.Accounts; import org.mariotaku.twidere.provider.TweetStore.Accounts;
import org.mariotaku.twidere.util.ImageLoaderWrapper; import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.view.holder.AccountViewHolder; import org.mariotaku.twidere.view.holder.AccountViewHolder;
@ -41,11 +43,12 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
private final ImageLoaderWrapper mImageLoader; private final ImageLoaderWrapper mImageLoader;
private final SharedPreferences mPreferences; private final SharedPreferences mPreferences;
private int mUserColorIdx, mProfileImageIdx, mScreenNameIdx, mAccountIdIdx;
private long mDefaultAccountId; private long mDefaultAccountId;
private boolean mDisplayProfileImage; private boolean mDisplayProfileImage;
private int mChoiceMode; private int mChoiceMode;
private boolean mSortEnabled;
private Indices mIndices;
public AccountsAdapter(final Context context) { public AccountsAdapter(final Context context) {
super(context, R.layout.list_item_account, null, new String[]{Accounts.NAME}, super(context, R.layout.list_item_account, null, new String[]{Accounts.NAME},
@ -55,15 +58,21 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
} }
public Account getAccount(int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
return new Account(c, mIndices);
}
@Override @Override
public void bindView(final View view, final Context context, final Cursor cursor) { public void bindView(final View view, final Context context, final Cursor cursor) {
final int color = cursor.getInt(mUserColorIdx); final int color = cursor.getInt(mIndices.color);
final AccountViewHolder holder = (AccountViewHolder) view.getTag(); final AccountViewHolder holder = (AccountViewHolder) view.getTag();
holder.screen_name.setText("@" + cursor.getString(mScreenNameIdx)); holder.screen_name.setText("@" + cursor.getString(mIndices.screen_name));
holder.setAccountColor(color); holder.setAccountColor(color);
holder.setIsDefault(mDefaultAccountId != -1 && mDefaultAccountId == cursor.getLong(mAccountIdIdx)); holder.setIsDefault(mDefaultAccountId != -1 && mDefaultAccountId == cursor.getLong(mIndices.account_id));
if (mDisplayProfileImage) { if (mDisplayProfileImage) {
mImageLoader.displayProfileImage(holder.profile_image, cursor.getString(mProfileImageIdx)); mImageLoader.displayProfileImage(holder.profile_image, cursor.getString(mIndices.profile_image_url));
} else { } else {
mImageLoader.cancelDisplayTask(holder.profile_image); mImageLoader.cancelDisplayTask(holder.profile_image);
holder.profile_image.setImageResource(R.drawable.ic_profile_image_default); holder.profile_image.setImageResource(R.drawable.ic_profile_image_default);
@ -71,6 +80,7 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
final boolean isMultipleChoice = mChoiceMode == ListView.CHOICE_MODE_MULTIPLE final boolean isMultipleChoice = mChoiceMode == ListView.CHOICE_MODE_MULTIPLE
|| mChoiceMode == ListView.CHOICE_MODE_MULTIPLE_MODAL; || mChoiceMode == ListView.CHOICE_MODE_MULTIPLE_MODAL;
holder.checkbox.setVisibility(isMultipleChoice ? View.VISIBLE : View.GONE); holder.checkbox.setVisibility(isMultipleChoice ? View.VISIBLE : View.GONE);
holder.setSortEnabled(mSortEnabled);
super.bindView(view, context, cursor); super.bindView(view, context, cursor);
} }
@ -173,11 +183,14 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
@Override @Override
public Cursor swapCursor(final Cursor cursor) { public Cursor swapCursor(final Cursor cursor) {
if (cursor != null) { if (cursor != null) {
mAccountIdIdx = cursor.getColumnIndex(Accounts.ACCOUNT_ID); mIndices = new Indices(cursor);
mUserColorIdx = cursor.getColumnIndex(Accounts.COLOR);
mProfileImageIdx = cursor.getColumnIndex(Accounts.PROFILE_IMAGE_URL);
mScreenNameIdx = cursor.getColumnIndex(Accounts.SCREEN_NAME);
} }
return super.swapCursor(cursor); return super.swapCursor(cursor);
} }
public void setSortEnabled(boolean sortEnabled) {
if (mSortEnabled == sortEnabled) return;
mSortEnabled = sortEnabled;
notifyDataSetChanged();
}
} }

View File

@ -20,17 +20,13 @@
package org.mariotaku.twidere.fragment.support; package org.mariotaku.twidere.fragment.support;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuff.Mode;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
@ -59,7 +55,6 @@ import org.mariotaku.twidere.activity.FiltersActivity;
import org.mariotaku.twidere.activity.SettingsActivity; import org.mariotaku.twidere.activity.SettingsActivity;
import org.mariotaku.twidere.activity.iface.IThemedActivity; import org.mariotaku.twidere.activity.iface.IThemedActivity;
import org.mariotaku.twidere.activity.support.AccountsManagerActivity; import org.mariotaku.twidere.activity.support.AccountsManagerActivity;
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
import org.mariotaku.twidere.activity.support.DraftsActivity; import org.mariotaku.twidere.activity.support.DraftsActivity;
import org.mariotaku.twidere.activity.support.HomeActivity; import org.mariotaku.twidere.activity.support.HomeActivity;
import org.mariotaku.twidere.activity.support.UserProfileEditorActivity; import org.mariotaku.twidere.activity.support.UserProfileEditorActivity;
@ -67,11 +62,6 @@ import org.mariotaku.twidere.adapter.ArrayAdapter;
import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.Account; import org.mariotaku.twidere.model.Account;
import org.mariotaku.twidere.provider.TweetStore.Accounts; import org.mariotaku.twidere.provider.TweetStore.Accounts;
import org.mariotaku.twidere.provider.TweetStore.DirectMessages;
import org.mariotaku.twidere.provider.TweetStore.DirectMessages.Inbox;
import org.mariotaku.twidere.provider.TweetStore.DirectMessages.Outbox;
import org.mariotaku.twidere.provider.TweetStore.Mentions;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
import org.mariotaku.twidere.util.ImageLoaderWrapper; import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver; import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
@ -86,14 +76,12 @@ import static org.mariotaku.twidere.util.Utils.openUserLists;
import static org.mariotaku.twidere.util.Utils.openUserProfile; import static org.mariotaku.twidere.util.Utils.openUserProfile;
import static org.mariotaku.twidere.util.Utils.openUserTimeline; import static org.mariotaku.twidere.util.Utils.openUserTimeline;
public class AccountsDrawerFragment extends BaseSupportListFragment implements LoaderCallbacks<Cursor>, public class AccountsDashboardFragment extends BaseSupportListFragment implements LoaderCallbacks<Cursor>,
OnSharedPreferenceChangeListener, OnAccountActivateStateChangeListener { OnSharedPreferenceChangeListener, OnAccountActivateStateChangeListener {
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver( private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
this, 0, this); this, 0, this);
private static final String FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion";
private ContentResolver mResolver; private ContentResolver mResolver;
private SharedPreferences mPreferences; private SharedPreferences mPreferences;
private MergeAdapter mAdapter; private MergeAdapter mAdapter;
@ -106,10 +94,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
private Context mThemedContext; private Context mThemedContext;
public Account getSelectedAccount() {
return mAccountsAdapter.getSelectedAccount();
}
@Override @Override
public void onAccountActivateStateChanged(final Account account, final boolean activated) { public void onAccountActivateStateChanged(final Account account, final boolean activated) {
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
@ -151,16 +135,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
@Override @Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) { switch (requestCode) {
case REQUEST_SET_COLOR: {
if (resultCode == Activity.RESULT_OK) {
if (data == null) return;
final ContentValues values = new ContentValues();
values.put(Accounts.COLOR, data.getIntExtra(EXTRA_COLOR, Color.WHITE));
final String where = Accounts.ACCOUNT_ID + " = " + mAccountsAdapter.getSelectedAccountId();
mResolver.update(Accounts.CONTENT_URI, values, where, null);
}
return;
}
case REQUEST_SETTINGS: { case REQUEST_SETTINGS: {
if (data == null) return; if (data == null) return;
final FragmentActivity activity = getActivity(); final FragmentActivity activity = getActivity();
@ -243,25 +217,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
closeAccountsDrawer(); closeAccountsDrawer();
break; break;
} }
case MENU_SET_COLOR: {
final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class);
intent.putExtra(EXTRA_COLOR, account.color);
intent.putExtra(EXTRA_ALPHA_SLIDER, false);
startActivityForResult(intent, REQUEST_SET_COLOR);
break;
}
case MENU_SET_AS_DEFAULT: {
mPreferences.edit().putLong(KEY_DEFAULT_ACCOUNT_ID, account.account_id).apply();
break;
}
case MENU_DELETE: {
final AccountDeletionDialogFragment f = new AccountDeletionDialogFragment();
final Bundle args = new Bundle();
args.putLong(EXTRA_ACCOUNT_ID, account.account_id);
f.setArguments(args);
f.show(getChildFragmentManager(), FRAGMENT_TAG_ACCOUNT_DELETION);
break;
}
} }
} else if (adapter instanceof AppMenuAdapter) { } else if (adapter instanceof AppMenuAdapter) {
if (!(item instanceof OptionItem)) return; if (!(item instanceof OptionItem)) return;
@ -370,7 +325,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
private void updateDefaultAccountState() { private void updateDefaultAccountState() {
final long defaultAccountId = mAccountsAdapter.getDefaultAccountId(); final long defaultAccountId = mAccountsAdapter.getDefaultAccountId();
final long selectedAccountId = mAccountsAdapter.getSelectedAccountId(); final long selectedAccountId = mAccountsAdapter.getSelectedAccountId();
mAccountOptionsAdapter.setDefault(defaultAccountId == selectedAccountId);
} }
private static TextView newSectionView(final Context context, final int titleRes) { private static TextView newSectionView(final Context context, final int titleRes) {
@ -381,47 +335,10 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
return textView; return textView;
} }
public static final class AccountDeletionDialogFragment extends BaseSupportDialogFragment implements
DialogInterface.OnClickListener {
@Override
public void onClick(final DialogInterface dialog, final int which) {
final Bundle args = getArguments();
final long account_id = args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
if (account_id < 0) return;
final ContentResolver resolver = getContentResolver();
switch (which) {
case DialogInterface.BUTTON_POSITIVE: {
resolver.delete(Accounts.CONTENT_URI, Accounts.ACCOUNT_ID + " = " + account_id, null);
// Also delete tweets related to the account we previously
// deleted.
resolver.delete(Statuses.CONTENT_URI, Statuses.ACCOUNT_ID + " = " + account_id, null);
resolver.delete(Mentions.CONTENT_URI, Mentions.ACCOUNT_ID + " = " + account_id, null);
resolver.delete(Inbox.CONTENT_URI, DirectMessages.ACCOUNT_ID + " = " + account_id, null);
resolver.delete(Outbox.CONTENT_URI, DirectMessages.ACCOUNT_ID + " = " + account_id, null);
break;
}
}
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
builder.setNegativeButton(android.R.string.cancel, null);
builder.setPositiveButton(android.R.string.ok, this);
builder.setTitle(R.string.account_delete_confirm_title);
builder.setMessage(R.string.account_delete_confirm_message);
return builder.create();
}
}
private static final class AccountOptionsAdapter extends OptionItemsAdapter { private static final class AccountOptionsAdapter extends OptionItemsAdapter {
private static final ArrayList<OptionItem> sOptions = new ArrayList<>(); private static final ArrayList<OptionItem> sOptions = new ArrayList<>();
private static final ArrayList<OptionItem> sOptionsDefault = new ArrayList<>();
static { static {
sOptions.add(new OptionItem(R.string.view_user_profile, R.drawable.ic_action_profile, MENU_VIEW_PROFILE)); sOptions.add(new OptionItem(R.string.view_user_profile, R.drawable.ic_action_profile, MENU_VIEW_PROFILE));
@ -431,22 +348,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
sOptions.add(new OptionItem(R.string.users_lists, R.drawable.ic_action_list, MENU_LISTS)); sOptions.add(new OptionItem(R.string.users_lists, R.drawable.ic_action_list, MENU_LISTS));
sOptions.add(new OptionItem(R.string.lists_following_me, R.drawable.ic_action_list, sOptions.add(new OptionItem(R.string.lists_following_me, R.drawable.ic_action_list,
MENU_LIST_MEMBERSHIPS)); MENU_LIST_MEMBERSHIPS));
sOptions.add(new OptionItem(R.string.set_color, R.drawable.ic_action_color_palette, MENU_SET_COLOR));
sOptions.add(new OptionItem(R.string.set_as_default, R.drawable.ic_action_ok, MENU_SET_AS_DEFAULT));
sOptions.add(new OptionItem(R.string.delete, R.drawable.ic_action_delete, MENU_DELETE));
sOptionsDefault.add(new OptionItem(R.string.view_user_profile, R.drawable.ic_action_profile,
MENU_VIEW_PROFILE));
sOptionsDefault.add(new OptionItem(android.R.string.search_go, R.drawable.ic_action_search,
MENU_SEARCH));
sOptionsDefault.add(new OptionItem(R.string.statuses, R.drawable.ic_action_quote, MENU_STATUSES));
sOptionsDefault.add(new OptionItem(R.string.favorites, R.drawable.ic_action_star, MENU_FAVORITES));
sOptionsDefault.add(new OptionItem(R.string.users_lists, R.drawable.ic_action_list, MENU_LISTS));
sOptionsDefault.add(new OptionItem(R.string.lists_following_me, R.drawable.ic_action_list,
MENU_LIST_MEMBERSHIPS));
sOptionsDefault.add(new OptionItem(R.string.set_color, R.drawable.ic_action_color_palette,
MENU_SET_COLOR));
sOptionsDefault.add(new OptionItem(R.string.delete, R.drawable.ic_action_delete, MENU_DELETE));
} }
public AccountOptionsAdapter(final Context context) { public AccountOptionsAdapter(final Context context) {
@ -455,10 +356,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
addAll(sOptions); addAll(sOptions);
} }
public void setDefault(final boolean isDefault) {
clear();
addAll(isDefault ? sOptionsDefault : sOptions);
}
} }
private static final class AppMenuAdapter extends OptionItemsAdapter { private static final class AppMenuAdapter extends OptionItemsAdapter {

View File

@ -1,15 +1,27 @@
package org.mariotaku.twidere.fragment.support; package org.mariotaku.twidere.fragment.support;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader; import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -17,6 +29,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AbsListView; import android.widget.AbsListView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView; import android.widget.ListView;
import com.mobeta.android.dslv.DragSortListView; import com.mobeta.android.dslv.DragSortListView;
@ -24,9 +37,17 @@ import com.mobeta.android.dslv.DragSortListView.DropListener;
import org.mariotaku.querybuilder.Where; import org.mariotaku.querybuilder.Where;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
import org.mariotaku.twidere.activity.support.SignInActivity; import org.mariotaku.twidere.activity.support.SignInActivity;
import org.mariotaku.twidere.adapter.AccountsAdapter; import org.mariotaku.twidere.adapter.AccountsAdapter;
import org.mariotaku.twidere.model.Account;
import org.mariotaku.twidere.provider.TweetStore.Accounts; import org.mariotaku.twidere.provider.TweetStore.Accounts;
import org.mariotaku.twidere.provider.TweetStore.DirectMessages;
import org.mariotaku.twidere.provider.TweetStore.DirectMessages.Inbox;
import org.mariotaku.twidere.provider.TweetStore.DirectMessages.Outbox;
import org.mariotaku.twidere.provider.TweetStore.Mentions;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.Utils;
import java.util.ArrayList; import java.util.ArrayList;
@ -34,9 +55,13 @@ import java.util.ArrayList;
/** /**
* Created by mariotaku on 14/10/26. * Created by mariotaku on 14/10/26.
*/ */
public class AccountsManagerFragment extends BaseSupportListFragment implements LoaderCallbacks<Cursor>, DropListener { public class AccountsManagerFragment extends BaseSupportListFragment implements LoaderCallbacks<Cursor>, DropListener, OnSharedPreferenceChangeListener {
private static final String FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion";
private AccountsAdapter mAdapter; private AccountsAdapter mAdapter;
private SharedPreferences mPreferences;
private Account mSelectedAccount;
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
@ -51,22 +76,136 @@ public class AccountsManagerFragment extends BaseSupportListFragment implements
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_SET_COLOR: {
if (resultCode != Activity.RESULT_OK || data == null || mSelectedAccount == null)
return;
final ContentValues values = new ContentValues();
values.put(Accounts.COLOR, data.getIntExtra(EXTRA_COLOR, Color.WHITE));
final String where = Accounts.ACCOUNT_ID + " = " + mSelectedAccount.account_id;
final ContentResolver cr = getContentResolver();
cr.update(Accounts.CONTENT_URI, values, where, null);
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_accounts_manager, menu); inflater.inflate(R.menu.menu_accounts_manager, menu);
} }
@Override
public boolean onContextItemSelected(MenuItem item) {
final ContextMenuInfo menuInfo = item.getMenuInfo();
if (!(menuInfo instanceof AdapterContextMenuInfo)) return false;
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
mSelectedAccount = mAdapter.getAccount(info.position);
if (mSelectedAccount == null) return false;
switch (item.getItemId()) {
case MENU_SET_AS_DEFAULT: {
final Editor editor = mPreferences.edit();
editor.putLong(KEY_DEFAULT_ACCOUNT_ID, mSelectedAccount.account_id);
editor.apply();
return true;
}
case MENU_SET_COLOR: {
final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class);
intent.putExtra(EXTRA_COLOR, mSelectedAccount.color);
intent.putExtra(EXTRA_ALPHA_SLIDER, false);
startActivityForResult(intent, REQUEST_SET_COLOR);
break;
}
case MENU_DELETE: {
final AccountDeletionDialogFragment f = new AccountDeletionDialogFragment();
final Bundle args = new Bundle();
args.putLong(EXTRA_ACCOUNT_ID, mSelectedAccount.account_id);
f.setArguments(args);
f.show(getChildFragmentManager(), FRAGMENT_TAG_ACCOUNT_DELETION);
break;
}
}
return false;
}
public static final class AccountDeletionDialogFragment extends BaseSupportDialogFragment implements
DialogInterface.OnClickListener {
@Override
public void onClick(final DialogInterface dialog, final int which) {
final Bundle args = getArguments();
final long account_id = args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
if (account_id < 0) return;
final ContentResolver resolver = getContentResolver();
switch (which) {
case DialogInterface.BUTTON_POSITIVE: {
resolver.delete(Accounts.CONTENT_URI, Accounts.ACCOUNT_ID + " = " + account_id, null);
// Also delete tweets related to the account we previously
// deleted.
resolver.delete(Statuses.CONTENT_URI, Statuses.ACCOUNT_ID + " = " + account_id, null);
resolver.delete(Mentions.CONTENT_URI, Mentions.ACCOUNT_ID + " = " + account_id, null);
resolver.delete(Inbox.CONTENT_URI, DirectMessages.ACCOUNT_ID + " = " + account_id, null);
resolver.delete(Outbox.CONTENT_URI, DirectMessages.ACCOUNT_ID + " = " + account_id, null);
break;
}
}
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
builder.setNegativeButton(android.R.string.cancel, null);
builder.setPositiveButton(android.R.string.ok, this);
builder.setTitle(R.string.account_delete_confirm_title);
builder.setMessage(R.string.account_delete_confirm_message);
return builder.create();
}
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
l.showContextMenuForChild(v);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
if (!(menuInfo instanceof AdapterContextMenuInfo)) return;
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
final Account account = mAdapter.getAccount(info.position);
menu.setHeaderTitle(account.name);
final MenuInflater inflater = new MenuInflater(v.getContext());
inflater.inflate(R.menu.action_manager_account, menu);
final boolean isDefault = Utils.getDefaultAccountId(getActivity()) == account.account_id;
Utils.setMenuItemAvailability(menu, MENU_SET_AS_DEFAULT, !isDefault);
}
@Override
public void onDestroyView() {
mPreferences.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroyView();
}
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
final FragmentActivity activity = getActivity(); final FragmentActivity activity = getActivity();
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mPreferences.registerOnSharedPreferenceChangeListener(this);
mAdapter = new AccountsAdapter(activity); mAdapter = new AccountsAdapter(activity);
Utils.configBaseAdapter(activity, mAdapter); Utils.configBaseAdapter(activity, mAdapter);
setListAdapter(mAdapter); setListAdapter(mAdapter);
final DragSortListView listView = (DragSortListView) getListView(); final DragSortListView listView = (DragSortListView) getListView();
listView.setDragEnabled(true); listView.setDragEnabled(true);
listView.setDropListener(this); listView.setDropListener(this);
listView.setOnCreateContextMenuListener(this);
getLoaderManager().initLoader(0, null, this); getLoaderManager().initLoader(0, null, this);
} }
@ -123,4 +262,15 @@ public class AccountsManagerFragment extends BaseSupportListFragment implements
} }
} }
} }
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (KEY_DEFAULT_ACCOUNT_ID.equals(key)) {
updateDefaultAccount();
}
}
private void updateDefaultAccount() {
mAdapter.notifyDataSetChanged();
}
} }

View File

@ -32,6 +32,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
@ -60,7 +61,6 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener; import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
@ -87,6 +87,7 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ContentValuesCreator; import org.mariotaku.twidere.util.ContentValuesCreator;
import org.mariotaku.twidere.util.FlymeUtils; import org.mariotaku.twidere.util.FlymeUtils;
import org.mariotaku.twidere.util.ImageLoaderWrapper; import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.MathUtils;
import org.mariotaku.twidere.util.ParseUtils; import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereLinkify; import org.mariotaku.twidere.util.TwidereLinkify;
@ -95,6 +96,7 @@ import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.menu.TwidereMenuInfo; import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
import org.mariotaku.twidere.view.ColorLabelLinearLayout; import org.mariotaku.twidere.view.ColorLabelLinearLayout;
import org.mariotaku.twidere.view.ExtendedFrameLayout; import org.mariotaku.twidere.view.ExtendedFrameLayout;
import org.mariotaku.twidere.view.ProfileBannerImageView;
import org.mariotaku.twidere.view.ProfileImageView; import org.mariotaku.twidere.view.ProfileImageView;
import org.mariotaku.twidere.view.TwidereMenuBar; import org.mariotaku.twidere.view.TwidereMenuBar;
import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener; import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener;
@ -152,7 +154,7 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
private SharedPreferences mPreferences; private SharedPreferences mPreferences;
private ProfileImageView mProfileImageView; private ProfileImageView mProfileImageView;
private ImageView mProfileBannerView; private ProfileBannerImageView mProfileBannerView;
private TextView mNameView, mScreenNameView, mDescriptionView, mLocationView, mURLView, mCreatedAtView, private TextView mNameView, mScreenNameView, mDescriptionView, mLocationView, mURLView, mCreatedAtView,
mTweetCount, mFollowersCount, mFriendsCount, mErrorMessageView; mTweetCount, mFollowersCount, mFriendsCount, mErrorMessageView;
private View mDescriptionContainer, mLocationContainer, mURLContainer, mTweetsContainer, mFollowersContainer, private View mDescriptionContainer, mLocationContainer, mURLContainer, mTweetsContainer, mFollowersContainer,
@ -164,9 +166,9 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
private View mErrorRetryContainer; private View mErrorRetryContainer;
private View mFollowingYouIndicator; private View mFollowingYouIndicator;
private View mMainContent; private View mMainContent;
private View mProfileBannerSpace;
private ProgressBar mDetailsLoadProgress; private ProgressBar mDetailsLoadProgress;
private TwidereMenuBar mMenuBar; private TwidereMenuBar mMenuBar;
private View mProfileBannerSpace;
private ListActionAdapter mAdapter; private ListActionAdapter mAdapter;
@ -385,7 +387,9 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
final String where = Accounts.ACCOUNT_ID + " = " + user.id; final String where = Accounts.ACCOUNT_ID + " = " + user.id;
resolver.update(Accounts.CONTENT_URI, values, where, null); resolver.update(Accounts.CONTENT_URI, values, where, null);
} }
if (Utils.isOfficialKeyAccount(getActivity(), user.account_id)) {
mAdapter.add(new MediaTimelineAction(1)); mAdapter.add(new MediaTimelineAction(1));
}
mAdapter.add(new FavoritesAction(2)); mAdapter.add(new FavoritesAction(2));
mAdapter.add(new UserMentionsAction(3)); mAdapter.add(new UserMentionsAction(3));
mAdapter.add(new UserListsAction(4)); mAdapter.add(new UserListsAction(4));
@ -464,8 +468,9 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
mFollowersContainer.setOnClickListener(this); mFollowersContainer.setOnClickListener(this);
mFriendsContainer.setOnClickListener(this); mFriendsContainer.setOnClickListener(this);
mRetryButton.setOnClickListener(this); mRetryButton.setOnClickListener(this);
mProfileBannerView.setOnSizeChangedListener(this);
mProfileBannerSpace.setOnTouchListener(this);
setListAdapter(null); setListAdapter(null);
mListView = getListView();
mListView.addHeaderView(mHeaderView, null, false); mListView.addHeaderView(mHeaderView, null, false);
if (isUucky(userId, screenName, args.getParcelable(EXTRA_USER))) { if (isUucky(userId, screenName, args.getParcelable(EXTRA_USER))) {
final View uuckyFooter = View.inflate(activity, final View uuckyFooter = View.inflate(activity,
@ -480,8 +485,6 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
mMenuBar.setIsBottomBar(true); mMenuBar.setIsBottomBar(true);
mMenuBar.setOnMenuItemClickListener(this); mMenuBar.setOnMenuItemClickListener(this);
mProfileBannerSpace.setOnTouchListener(this);
setListAdapter(mAdapter); setListAdapter(mAdapter);
getUserInfo(accountId, userId, screenName, false); getUserInfo(accountId, userId, screenName, false);
@ -498,13 +501,17 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
final int themeResId = linkHandler.getCurrentThemeResourceId(); final int themeResId = linkHandler.getCurrentThemeResourceId();
final boolean isTransparent = ThemeUtils.isTransparentBackground(themeResId); final boolean isTransparent = ThemeUtils.isTransparentBackground(themeResId);
final int actionBarAlpha = isTransparent ? ThemeUtils.getUserThemeBackgroundAlpha(linkHandler) : 0xFF; final int actionBarAlpha = isTransparent ? ThemeUtils.getUserThemeBackgroundAlpha(linkHandler) : 0xFF;
if (ThemeUtils.isColoredActionBar(themeResId)) { if (ThemeUtils.isColoredActionBar(themeResId) && useUserActionBar()) {
actionBar.setBackgroundDrawable(mActionBarBackground = new ColorDrawable(themeColor)); actionBar.setBackgroundDrawable(mActionBarBackground = new ColorDrawable(themeColor));
} else { } else {
actionBar.setBackgroundDrawable(mActionBarBackground = ThemeUtils.getActionBarBackground(activity, themeResId)); actionBar.setBackgroundDrawable(mActionBarBackground = ThemeUtils.getActionBarBackground(activity, themeResId));
} }
} }
private boolean useUserActionBar() {
return false;
}
private boolean isUucky(long userId, String screenName, Parcelable parcelable) { private boolean isUucky(long userId, String screenName, Parcelable parcelable) {
if (userId == UUCKY_ID || UUCKY_SCREEN_NAME.equalsIgnoreCase(screenName)) return true; if (userId == UUCKY_ID || UUCKY_SCREEN_NAME.equalsIgnoreCase(screenName)) return true;
if (parcelable instanceof ParcelableUser) { if (parcelable instanceof ParcelableUser) {
@ -567,25 +574,21 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
openImage(activity, user.account_id, profile_image_url_string, false); openImage(activity, user.account_id, profile_image_url_string, false);
break; break;
} }
case R.id.profile_banner: case R.id.profile_banner: {
case R.id.profile_banner_space: {
final String profile_banner_url = mUser.profile_banner_url; final String profile_banner_url = mUser.profile_banner_url;
if (profile_banner_url == null) return; if (profile_banner_url == null) return;
openImage(getActivity(), user.account_id, profile_banner_url + "/ipad_retina", false); openImage(getActivity(), user.account_id, profile_banner_url + "/ipad_retina", false);
break; break;
} }
case R.id.tweets_container: { case R.id.tweets_container: {
if (mUser == null) return;
openUserTimeline(getActivity(), user.account_id, user.id, user.screen_name); openUserTimeline(getActivity(), user.account_id, user.id, user.screen_name);
break; break;
} }
case R.id.followers_container: { case R.id.followers_container: {
if (mUser == null) return;
openUserFollowers(getActivity(), user.account_id, user.id, user.screen_name); openUserFollowers(getActivity(), user.account_id, user.id, user.screen_name);
break; break;
} }
case R.id.friends_container: { case R.id.friends_container: {
if (mUser == null) return;
openUserFriends(getActivity(), user.account_id, user.id, user.screen_name); openUserFriends(getActivity(), user.account_id, user.id, user.screen_name);
break; break;
} }
@ -635,8 +638,7 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
@Override @Override
public boolean onItemLongClick(final AdapterView<?> adapter, final View view, final int position, final long id) { public boolean onItemLongClick(final AdapterView<?> adapter, final View view, final int position, final long id) {
final ListAction action = mAdapter.findItem(id); final ListAction action = mAdapter.findItem(id);
if (action != null) return action.onLongClick(); return action != null && action.onLongClick();
return false;
} }
@Override @Override
@ -710,14 +712,19 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount, public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
final int totalItemCount) { final int totalItemCount) {
super.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); super.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
final View headerView = mHeaderView, profileBannerView = mProfileBannerView; final View headerView = mHeaderView;
if (headerView == null || profileBannerView == null) return; final ProfileBannerImageView profileBannerView = mProfileBannerView;
final ListView listView = mListView;
if (headerView == null || profileBannerView == null || listView == null) return;
final float factor = -headerView.getTop() / (float) headerView.getHeight(); final float factor = -headerView.getTop() / (float) headerView.getHeight();
final int headerScroll = listView.getListPaddingTop() - headerView.getTop();
profileBannerView.setAlpha(1.0f - factor); profileBannerView.setAlpha(1.0f - factor);
profileBannerView.setTranslationY(headerView.getTop() / 2); profileBannerView.setTranslationY((headerView.getTop() - listView.getListPaddingTop()) / 2);
profileBannerView.setBottomClip(headerScroll);
if (mActionBarBackground != null) { if (mActionBarBackground != null) {
mActionBarBackground.setAlpha(Math.round(0xFF * factor)); final float f = headerScroll / (float) mProfileBannerSpace.getHeight();
mActionBarBackground.setAlpha(Math.round(0xFF * MathUtils.clamp(f, 0, 1)));
} }
} }
@ -730,6 +737,9 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
@Override @Override
public void onSizeChanged(final View view, final int w, final int h, final int oldw, final int oldh) { public void onSizeChanged(final View view, final int w, final int h, final int oldw, final int oldh) {
mBannerWidth = w; mBannerWidth = w;
if (w != oldw || h != oldh) {
requestFitSystemWindows();
}
} }
@Override @Override
@ -754,17 +764,26 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
return mProfileBannerView.dispatchTouchEvent(event); return mProfileBannerView.dispatchTouchEvent(event);
} }
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
final ViewGroup.LayoutParams params = mProfileBannerSpace.getLayoutParams();
params.height = Math.max(insets.top, mProfileBannerView.getHeight() - insets.top);
mProfileBannerSpace.setLayoutParams(params);
}
@Override @Override
public void onViewCreated(final View view, final Bundle savedInstanceState) { public void onViewCreated(final View view, final Bundle savedInstanceState) {
final Context context = view.getContext(); final Context context = view.getContext();
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
mMainContent = view.findViewById(R.id.content); mMainContent = view.findViewById(R.id.content);
mListView = (ListView) view.findViewById(android.R.id.list);
mDetailsLoadProgress = (ProgressBar) view.findViewById(R.id.details_load_progress); mDetailsLoadProgress = (ProgressBar) view.findViewById(R.id.details_load_progress);
mMenuBar = (TwidereMenuBar) view.findViewById(R.id.menu_bar); mMenuBar = (TwidereMenuBar) view.findViewById(R.id.menu_bar);
mErrorRetryContainer = view.findViewById(R.id.error_retry_container); mErrorRetryContainer = view.findViewById(R.id.error_retry_container);
mRetryButton = (Button) view.findViewById(R.id.retry); mRetryButton = (Button) view.findViewById(R.id.retry);
mErrorMessageView = (TextView) view.findViewById(R.id.error_message); mErrorMessageView = (TextView) view.findViewById(R.id.error_message);
mProfileBannerView = (ImageView) view.findViewById(R.id.profile_banner); mProfileBannerView = (ProfileBannerImageView) view.findViewById(R.id.profile_banner);
mNameView = (TextView) mHeaderView.findViewById(R.id.name); mNameView = (TextView) mHeaderView.findViewById(R.id.name);
mScreenNameView = (TextView) mHeaderView.findViewById(R.id.screen_name); mScreenNameView = (TextView) mHeaderView.findViewById(R.id.screen_name);
mDescriptionView = (TextView) mHeaderView.findViewById(R.id.description); mDescriptionView = (TextView) mHeaderView.findViewById(R.id.description);

View File

@ -68,7 +68,7 @@ public class Account implements Parcelable {
profile_image_url = indices.profile_image_url != -1 ? cursor.getString(indices.profile_image_url) : null; profile_image_url = indices.profile_image_url != -1 ? cursor.getString(indices.profile_image_url) : null;
profile_banner_url = indices.profile_banner_url != -1 ? cursor.getString(indices.profile_banner_url) : null; profile_banner_url = indices.profile_banner_url != -1 ? cursor.getString(indices.profile_banner_url) : null;
color = indices.color != -1 ? cursor.getInt(indices.color) : Color.TRANSPARENT; color = indices.color != -1 ? cursor.getInt(indices.color) : Color.TRANSPARENT;
is_activated = indices.is_activated != -1 ? cursor.getInt(indices.is_activated) == 1 : false; is_activated = indices.is_activated != -1 && cursor.getInt(indices.is_activated) == 1;
} }
public Account(final Parcel source) { public Account(final Parcel source) {

View File

@ -264,14 +264,14 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
id = orig.getId(); id = orig.getId();
timestamp = getTime(orig.getCreatedAt()); timestamp = getTime(orig.getCreatedAt());
is_retweet = orig.isRetweet(); is_retweet = orig.isRetweet();
final Status retweeted_status = orig.getRetweetedStatus(); final Status retweeted = orig.getRetweetedStatus();
final User retweet_user = retweeted_status != null ? orig.getUser() : null; final User retweet_user = retweeted != null ? orig.getUser() : null;
retweet_id = retweeted_status != null ? retweeted_status.getId() : -1; retweet_id = retweeted != null ? retweeted.getId() : -1;
retweet_timestamp = retweeted_status != null ? getTime(orig.getCreatedAt()) : -1; retweet_timestamp = retweeted != null ? getTime(retweeted.getCreatedAt()) : -1;
retweeted_by_id = retweet_user != null ? retweet_user.getId() : -1; retweeted_by_id = retweet_user != null ? retweet_user.getId() : -1;
retweeted_by_name = retweet_user != null ? retweet_user.getName() : null; retweeted_by_name = retweet_user != null ? retweet_user.getName() : null;
retweeted_by_screen_name = retweet_user != null ? retweet_user.getScreenName() : null; retweeted_by_screen_name = retweet_user != null ? retweet_user.getScreenName() : null;
final Status status = retweeted_status != null ? retweeted_status : orig; final Status status = retweeted != null ? retweeted : orig;
final User user = status.getUser(); final User user = status.getUser();
user_id = user.getId(); user_id = user.getId();
user_name = user.getName(); user_name = user.getName();

View File

@ -21,15 +21,19 @@ package org.mariotaku.twidere.preference;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory; import android.preference.PreferenceCategory;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.CompoundButton.OnCheckedChangeListener;
@ -52,7 +56,7 @@ import java.util.List;
public abstract class AccountsListPreference extends PreferenceCategory implements Constants { public abstract class AccountsListPreference extends PreferenceCategory implements Constants {
private static final int[] ATTRS = { R.attr.switchKey, R.attr.switchDefault }; private static final int[] ATTRS = {R.attr.switchKey, R.attr.switchDefault};
private final String mSwitchKey; private final String mSwitchKey;
private final boolean mSwitchDefault; private final boolean mSwitchDefault;
@ -94,22 +98,20 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
protected abstract void setupPreference(AccountItemPreference preference, Account account); protected abstract void setupPreference(AccountItemPreference preference, Account account);
public static final class AccountItemPreference extends Preference implements ImageLoadingListener, public static final class AccountItemPreference extends Preference implements ImageLoadingListener,
OnCheckedChangeListener, OnSharedPreferenceChangeListener { OnCheckedChangeListener, OnSharedPreferenceChangeListener, OnPreferenceClickListener, OnClickListener {
private final Account mAccount; private final Account mAccount;
private final SharedPreferences mSwitchPreference; private final SharedPreferences mSwitchPreference;
private final String mSwitchKey; private final String mSwitchKey;
private final boolean mSwitchDefault; private final boolean mSwitchDefault;
private final float mDensity;
private View mView;
public AccountItemPreference(final Context context, final Account account, final String switchKey, public AccountItemPreference(final Context context, final Account account, final String switchKey,
final boolean switchDefault) { final boolean switchDefault) {
super(context); super(context);
setWidgetLayoutResource(R.layout.preference_widget_account_preference_item);
setOnPreferenceClickListener(this);
final String switchPreferenceName = ACCOUNT_PREFERENCES_NAME_PREFIX + account.account_id; final String switchPreferenceName = ACCOUNT_PREFERENCES_NAME_PREFIX + account.account_id;
mAccount = account; mAccount = account;
mDensity = context.getResources().getDisplayMetrics().density;
mSwitchPreference = context.getSharedPreferences(switchPreferenceName, Context.MODE_PRIVATE); mSwitchPreference = context.getSharedPreferences(switchPreferenceName, Context.MODE_PRIVATE);
mSwitchKey = switchKey; mSwitchKey = switchKey;
mSwitchDefault = switchDefault; mSwitchDefault = switchDefault;
@ -146,11 +148,11 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
@Override @Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) { public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
updateSwitchState(); notifyChanged();
} }
@Override @Override
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) { protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) {
super.onAttachedToHierarchy(preferenceManager); super.onAttachedToHierarchy(preferenceManager);
setTitle(mAccount.name); setTitle(mAccount.name);
setSummary(String.format("@%s", mAccount.screen_name)); setSummary(String.format("@%s", mAccount.screen_name));
@ -161,9 +163,17 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
} }
@Override @Override
protected void onBindView(final View view) { protected View onCreateView(ViewGroup parent) {
final View view = super.onCreateView(parent);
view.findViewById(R.id.settings).setOnClickListener(this);
final Switch toggle = (Switch) view.findViewById(android.R.id.toggle);
toggle.setOnCheckedChangeListener(this);
return view;
}
@Override
protected void onBindView(@NonNull final View view) {
super.onBindView(view); super.onBindView(view);
mView = view;
final View iconView = view.findViewById(android.R.id.icon); final View iconView = view.findViewById(android.R.id.icon);
if (iconView instanceof ImageView) { if (iconView instanceof ImageView) {
((ImageView) iconView).setScaleType(ScaleType.FIT_CENTER); ((ImageView) iconView).setScaleType(ScaleType.FIT_CENTER);
@ -176,36 +186,25 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
if (summaryView instanceof TextView) { if (summaryView instanceof TextView) {
((TextView) summaryView).setSingleLine(true); ((TextView) summaryView).setSingleLine(true);
} }
updateSwitchState(); final Switch toggle = (Switch) view.findViewById(android.R.id.toggle);
}
private void updateSwitchState() {
if (mView == null) return;
final View widgetFrameView = mView.findViewById(android.R.id.widget_frame);
if (!(widgetFrameView instanceof ViewGroup)) return;
final ViewGroup widgetFrame = (ViewGroup) widgetFrameView;
widgetFrame.setVisibility(mSwitchKey != null ? View.VISIBLE : View.GONE);
widgetFrame.setPadding(widgetFrame.getPaddingLeft(), widgetFrame.getPaddingTop(), (int) (mDensity * 8),
widgetFrame.getPaddingBottom());
widgetFrame.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
// remove preview image that is already created
widgetFrame.setAlpha(isEnabled() ? 1 : 0.25f);
final View foundView = widgetFrame.findViewById(android.R.id.toggle);
final Switch toggle;
if (foundView instanceof Switch) {
toggle = (Switch) foundView;
} else {
widgetFrame.removeAllViews();
toggle = new Switch(getContext());
toggle.setId(android.R.id.toggle);
toggle.setOnCheckedChangeListener(this);
widgetFrame.addView(toggle);
}
if (mSwitchKey != null) { if (mSwitchKey != null) {
toggle.setChecked(mSwitchPreference.getBoolean(mSwitchKey, mSwitchDefault)); toggle.setChecked(mSwitchPreference.getBoolean(mSwitchKey, mSwitchDefault));
} }
} }
@Override
public boolean onPreferenceClick(Preference preference) {
return true;
}
@Override
public void onClick(View v) {
final Context context = getContext();
if (!(context instanceof PreferenceActivity)) return;
final PreferenceActivity activity = (PreferenceActivity) context;
activity.startPreferencePanel(getFragment(), getExtras(), getTitleRes(), getTitle(), null, 0);
}
} }
private static class LoadAccountsTask extends AsyncTask<Void, Void, List<Account>> { private static class LoadAccountsTask extends AsyncTask<Void, Void, List<Account>> {

View File

@ -43,10 +43,13 @@ public class SeekBarDialogPreference extends DialogPreference {
private static final int DEFAULT_MIN_PROGRESS = 0; private static final int DEFAULT_MIN_PROGRESS = 0;
private static final int DEFAULT_MAX_PROGRESS = 100; private static final int DEFAULT_MAX_PROGRESS = 100;
private static final int DEFAULT_PROGRESS = 0; private static final int DEFAULT_PROGRESS = 0;
private static final int DEFAULT_STEP = 1;
private int mMinProgress; private int mMinProgress;
private int mMaxProgress; private int mMaxProgress;
private int mProgress; private int mProgress;
private int mStep;
private CharSequence mProgressTextSuffix; private CharSequence mProgressTextSuffix;
private TextView mProgressText; private TextView mProgressText;
private SeekBar mSeekBar; private SeekBar mSeekBar;
@ -68,6 +71,7 @@ public class SeekBarDialogPreference extends DialogPreference {
try { try {
setMinProgress(a.getInteger(R.styleable.SeekBarDialogPreference_min, DEFAULT_MIN_PROGRESS)); setMinProgress(a.getInteger(R.styleable.SeekBarDialogPreference_min, DEFAULT_MIN_PROGRESS));
setMaxProgress(a.getInteger(R.styleable.SeekBarDialogPreference_max, DEFAULT_MAX_PROGRESS)); setMaxProgress(a.getInteger(R.styleable.SeekBarDialogPreference_max, DEFAULT_MAX_PROGRESS));
setStep(a.getInteger(R.styleable.SeekBarDialogPreference_step, DEFAULT_STEP));
setProgressTextSuffix(a.getString(R.styleable.SeekBarDialogPreference_progressTextSuffix)); setProgressTextSuffix(a.getString(R.styleable.SeekBarDialogPreference_progressTextSuffix));
} finally { } finally {
a.recycle(); a.recycle();
@ -80,6 +84,10 @@ public class SeekBarDialogPreference extends DialogPreference {
setDialogIcon(null); setDialogIcon(null);
} }
public void setStep(int step) {
mStep = step;
}
public int getMaxProgress() { public int getMaxProgress() {
return mMaxProgress; return mMaxProgress;
} }
@ -106,6 +114,9 @@ public class SeekBarDialogPreference extends DialogPreference {
setProgress(Math.max(mProgress, mMinProgress)); setProgress(Math.max(mProgress, mMinProgress));
} }
/**
* @param progress Real progress multiplied by steps
*/
public void setProgress(int progress) { public void setProgress(int progress) {
progress = Math.max(Math.min(progress, mMaxProgress), mMinProgress); progress = Math.max(Math.min(progress, mMaxProgress), mMinProgress);
@ -138,7 +149,7 @@ public class SeekBarDialogPreference extends DialogPreference {
// update text that displays the current SeekBar progress value // update text that displays the current SeekBar progress value
// note: this does not persist the progress value. that is only // note: this does not persist the progress value. that is only
// ever done in setProgress() // ever done in setProgress()
final String progressStr = String.valueOf(progress + mMinProgress); final String progressStr = String.valueOf(progress * mStep + mMinProgress);
mProgressText.setText(mProgressTextSuffix == null ? progressStr : progressStr mProgressText.setText(mProgressTextSuffix == null ? progressStr : progressStr
.concat(mProgressTextSuffix.toString())); .concat(mProgressTextSuffix.toString()));
} }
@ -151,8 +162,8 @@ public class SeekBarDialogPreference extends DialogPreference {
public void onStopTrackingTouch(final SeekBar seekBar) { public void onStopTrackingTouch(final SeekBar seekBar) {
} }
}); });
mSeekBar.setMax(mMaxProgress - mMinProgress); mSeekBar.setMax((int) Math.ceil((mMaxProgress - mMinProgress) / (double) mStep));
mSeekBar.setProgress(mProgress - mMinProgress); mSeekBar.setProgress((int) Math.ceil((mProgress - mMinProgress) / (double) mStep));
} }
@Override @Override
@ -161,9 +172,9 @@ public class SeekBarDialogPreference extends DialogPreference {
// when the user selects "OK", persist the new value // when the user selects "OK", persist the new value
if (positiveResult) { if (positiveResult) {
final int seekBarProgress = mSeekBar.getProgress() + mMinProgress; final int realProgress = mSeekBar.getProgress() * mStep + mMinProgress;
if (callChangeListener(seekBarProgress)) { if (callChangeListener(realProgress)) {
setProgress(seekBarProgress); setProgress(realProgress);
} }
} }
} }
@ -187,6 +198,7 @@ public class SeekBarDialogPreference extends DialogPreference {
setMinProgress(myState.minProgress); setMinProgress(myState.minProgress);
setMaxProgress(myState.maxProgress); setMaxProgress(myState.maxProgress);
setProgress(myState.progress); setProgress(myState.progress);
setStep(myState.step);
super.onRestoreInstanceState(myState.getSuperState()); super.onRestoreInstanceState(myState.getSuperState());
} }
@ -203,10 +215,14 @@ public class SeekBarDialogPreference extends DialogPreference {
myState.minProgress = getMinProgress(); myState.minProgress = getMinProgress();
myState.maxProgress = getMaxProgress(); myState.maxProgress = getMaxProgress();
myState.progress = getProgress(); myState.progress = getProgress();
myState.step = getStep();
return myState; return myState;
} }
private int getStep() {
return mStep;
}
@Override @Override
protected void onSetInitialValue(final boolean restore, final Object defaultValue) { protected void onSetInitialValue(final boolean restore, final Object defaultValue) {
setProgress(restore ? getPersistedInt(DEFAULT_PROGRESS) : (Integer) defaultValue); setProgress(restore ? getPersistedInt(DEFAULT_PROGRESS) : (Integer) defaultValue);
@ -216,6 +232,7 @@ public class SeekBarDialogPreference extends DialogPreference {
int minProgress; int minProgress;
int maxProgress; int maxProgress;
int progress; int progress;
int step;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
@ -236,6 +253,7 @@ public class SeekBarDialogPreference extends DialogPreference {
minProgress = source.readInt(); minProgress = source.readInt();
maxProgress = source.readInt(); maxProgress = source.readInt();
progress = source.readInt(); progress = source.readInt();
step = source.readInt();
} }
public SavedState(final Parcelable superState) { public SavedState(final Parcelable superState) {
@ -249,6 +267,7 @@ public class SeekBarDialogPreference extends DialogPreference {
dest.writeInt(minProgress); dest.writeInt(minProgress);
dest.writeInt(maxProgress); dest.writeInt(maxProgress);
dest.writeInt(progress); dest.writeInt(progress);
dest.writeInt(step);
} }
} }
} }

View File

@ -81,6 +81,7 @@ public class ThemeBackgroundPreference extends DialogPreference implements Const
@Override @Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
setValue(restorePersistedValue ? getPersistedString(mValue) : (String) defaultValue); setValue(restorePersistedValue ? getPersistedString(mValue) : (String) defaultValue);
updateSummary();
} }
private void updateSummary() { private void updateSummary() {
@ -90,7 +91,6 @@ public class ThemeBackgroundPreference extends DialogPreference implements Const
private void setValue(String value) { private void setValue(String value) {
mValue = value; mValue = value;
updateSummary();
updateAlphaVisibility(); updateAlphaVisibility();
} }

View File

@ -1,100 +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.util;
import static android.graphics.Color.WHITE;
import static android.graphics.Color.argb;
import static android.graphics.Color.blue;
import static android.graphics.Color.colorToHSV;
import static android.graphics.Color.green;
import static android.graphics.Color.red;
import android.graphics.Bitmap;
import android.graphics.Color;
import java.util.Collections;
import java.util.HashMap;
/**
* @author mariotaku Get the main color from a {@link Bitmap}<br>
* <br>
* <b>Important</b>: I recommand using this method in different thread.
* Or it may makes your application laggy.
*/
public final class ColorAnalyser {
/**
* Get the main color from a {@link Bitmap}.<br>
*
* @param bitmap The {@link Bitmap} to analyse
* @return The rgb {@link Color} in integer (no alpha)
*/
public static int analyse(final Bitmap bitmap) {
return analyse(bitmap, 18, 28);
}
/**
* Get the main color from a {@link Bitmap}.<br>
*
* @param bitmap The {@link Bitmap} to analyse
* @param width The desired width of scaled bitmap
* @param height The desired height of scaled bitmap
* @return The rgb {@link Color} in integer (no alpha)
*/
public static int analyse(final Bitmap bitmap, final int width, final int height) {
return analyse(bitmap, width, height, WHITE);
}
/**
* Get the main color from a {@link Bitmap}.<br>
*
* @param bitmap The {@link Bitmap} to analyse
* @param width The desired width of scaled bitmap
* @param height The desired height of scaled bitmap
* @param def The default color returned, if bitmap is null
* @return The rgb {@link Color} in integer (no alpha)
*/
public static int analyse(final Bitmap bitmap, final int width, final int height, final int def) {
if (bitmap == null) return def;
final HashMap<Float, Integer> colors = new HashMap<Float, Integer>();
final Bitmap resized = Bitmap.createScaledBitmap(bitmap, width, height, false);
final int resized_height = resized.getHeight(), resized_width = resized.getWidth();
for (int y = 0; y < resized_height; y++) {
for (int x = 0; x < resized_width; x++) {
final int temp_color = resized.getPixel(x, y);
final int color = argb(0xFF, red(temp_color), green(temp_color), blue(temp_color));
final float[] hsv = new float[3];
colorToHSV(color, hsv);
final float score = (hsv[1] * hsv[1] + 0.001f) * (hsv[2] * hsv[2]);
colors.put(score, color);
}
}
resized.recycle();
if (colors.size() == 0) return def;
return colors.get(Collections.max(colors.keySet()));
}
}

View File

@ -25,6 +25,7 @@ import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.Constants;
@ -55,6 +56,7 @@ public class ImageLoaderWrapper implements Constants {
bannerOptsBuilder.cacheInMemory(true); bannerOptsBuilder.cacheInMemory(true);
bannerOptsBuilder.cacheOnDisk(true); bannerOptsBuilder.cacheOnDisk(true);
bannerOptsBuilder.bitmapConfig(Bitmap.Config.RGB_565); bannerOptsBuilder.bitmapConfig(Bitmap.Config.RGB_565);
bannerOptsBuilder.displayer(new FadeInBitmapDisplayer(200, true, true, false));
mProfileImageDisplayOptions = profileOptsBuilder.build(); mProfileImageDisplayOptions = profileOptsBuilder.build();
mImageDisplayOptions = imageOptsBuilder.build(); mImageDisplayOptions = imageOptsBuilder.build();

View File

@ -2780,6 +2780,20 @@ public final class Utils implements Constants, TwitterConstants {
return false; return false;
} }
public static boolean isOfficialKeyAccount(final Context context, final long accountId) {
if (context == null) return false;
final String[] projection = {Accounts.CONSUMER_KEY, Accounts.CONSUMER_SECRET};
final String selection = Where.equals(Accounts.ACCOUNT_ID, accountId).getSQL();
final Cursor c = context.getContentResolver().query(Accounts.CONTENT_URI, projection, selection, null, null);
try {
if (c.moveToPosition(0))
return isOfficialConsumerKeySecret(context, c.getString(0), c.getString(1));
} finally {
c.close();
}
return false;
}
public static boolean isOfficialTwitterInstance(final Context context, final Twitter twitter) { public static boolean isOfficialTwitterInstance(final Context context, final Twitter twitter) {
if (context == null || twitter == null) return false; if (context == null || twitter == null) return false;
final Configuration conf = twitter.getConfiguration(); final Configuration conf = twitter.getConfiguration();

View File

@ -0,0 +1,28 @@
package org.mariotaku.twidere.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.widget.ImageButton;
/**
* Created by mariotaku on 14/11/5.
*/
public class ActionIconButton extends ImageButton {
public ActionIconButton(Context context) {
this(context, null);
}
public ActionIconButton(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.imageButtonStyle);
}
public ActionIconButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
final TypedArray a = context.obtainStyledAttributes(new int[]{android.R.attr.colorForeground});
setColorFilter(a.getColor(0, 0), Mode.SRC_ATOP);
a.recycle();
}
}

View File

@ -0,0 +1,32 @@
package org.mariotaku.twidere.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
import org.mariotaku.twidere.R;
/**
* Created by mariotaku on 14/11/14.
*/
public class AssetFontTextView extends TextView {
public AssetFontTextView(Context context) {
this(context, null);
}
public AssetFontTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AssetFontTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AssetFontTextView, defStyleAttr, 0);
final String path = a.getString(R.styleable.AssetFontTextView_fontPath);
if (path != null) {
setTypeface(Typeface.createFromAsset(context.getAssets(), path));
}
a.recycle();
}
}

View File

@ -19,9 +19,11 @@
package org.mariotaku.twidere.view; package org.mariotaku.twidere.view;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.ImageView; import android.widget.ImageView;
@ -49,6 +51,13 @@ public class ForegroundImageView extends ImageView implements IForegroundView {
return mForegroundViewHelper.getForeground(); return mForegroundViewHelper.getForeground();
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void drawableHotspotChanged(float x, float y) {
super.drawableHotspotChanged(x, y);
mForegroundViewHelper.dispatchDrawableHotspotChanged(x, y);
}
@Override @Override
public void jumpDrawablesToCurrentState() { public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState(); super.jumpDrawablesToCurrentState();
@ -62,7 +71,6 @@ public class ForegroundImageView extends ImageView implements IForegroundView {
* the padding area. * the padding area.
* *
* @param drawable The Drawable to be drawn on top of the children. * @param drawable The Drawable to be drawn on top of the children.
*
* @attr ref android.R.styleable#FrameLayout_foreground * @attr ref android.R.styleable#FrameLayout_foreground
*/ */
@Override @Override
@ -74,7 +82,6 @@ public class ForegroundImageView extends ImageView implements IForegroundView {
* Describes how the foreground is positioned. Defaults to START and TOP. * Describes how the foreground is positioned. Defaults to START and TOP.
* *
* @param foregroundGravity See {@link android.view.Gravity} * @param foregroundGravity See {@link android.view.Gravity}
*
* @attr ref android.R.styleable#FrameLayout_foregroundGravity * @attr ref android.R.styleable#FrameLayout_foregroundGravity
*/ */
@Override @Override

View File

@ -19,14 +19,12 @@
package org.mariotaku.twidere.view; package org.mariotaku.twidere.view;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode; import android.graphics.PorterDuffXfermode;
import android.graphics.Shader; import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -37,16 +35,11 @@ import org.mariotaku.twidere.view.iface.IExtendedView;
public class ProfileBannerImageView extends ForegroundImageView implements IExtendedView, Constants { public class ProfileBannerImageView extends ForegroundImageView implements IExtendedView, Constants {
private static final int[] COLORS = new int[] { 0xFFFFFFFF, 0x00FFFFFF };
private static final int[] COLORS_REVERSED = new int[] { 0x00FFFFFF, 0xFFFFFFFF };
private static final float[] POSITIONS = new float[] { 0.0f, 1.0f };
private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
private OnSizeChangedListener mOnSizeChangedListener; private OnSizeChangedListener mOnSizeChangedListener;
private TouchInterceptor mTouchInterceptor; private TouchInterceptor mTouchInterceptor;
private final Paint mPaint = new Paint(); private final Paint mClipPaint = new Paint();
private LinearGradient mShader; private int mBottomClip;
public ProfileBannerImageView(final Context context) { public ProfileBannerImageView(final Context context) {
this(context, null); this(context, null);
@ -59,15 +52,19 @@ public class ProfileBannerImageView extends ForegroundImageView implements IExte
public ProfileBannerImageView(final Context context, final AttributeSet attrs, final int defStyle) { public ProfileBannerImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
if (isInEditMode()) return; if (isInEditMode()) return;
ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, null);
setScaleType(ScaleType.CENTER_CROP); setScaleType(ScaleType.CENTER_CROP);
ViewCompat.setLayerType(this, LAYER_TYPE_SOFTWARE, null); // setForeground(ThemeUtils.getImageHighlightDrawable(context));
final boolean is_dark_theme = ThemeUtils.isDarkTheme(context); mClipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
COLORS_REVERSED[1] = is_dark_theme ? 0xFF000000 : 0xFFFFFFFF;
setForeground(ThemeUtils.getImageHighlightDrawable(context));
} }
@Override @Override
public final boolean dispatchTouchEvent(final MotionEvent event) { public boolean hasOverlappingRendering() {
return true;
}
@Override
public final boolean dispatchTouchEvent(@NonNull final MotionEvent event) {
if (mTouchInterceptor != null) { if (mTouchInterceptor != null) {
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event); final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
if (ret) return true; if (ret) return true;
@ -76,7 +73,7 @@ public class ProfileBannerImageView extends ForegroundImageView implements IExte
} }
@Override @Override
public final boolean onTouchEvent(final MotionEvent event) { public final boolean onTouchEvent(@NonNull final MotionEvent event) {
if (mTouchInterceptor != null) { if (mTouchInterceptor != null) {
final boolean ret = mTouchInterceptor.onTouchEvent(this, event); final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
if (ret) return true; if (ret) return true;
@ -94,25 +91,10 @@ public class ProfileBannerImageView extends ForegroundImageView implements IExte
mTouchInterceptor = listener; mTouchInterceptor = listener;
} }
@Override
protected void onDraw(final Canvas canvas) {
if (isInEditMode()) return;
final int width = getWidth(), height = getHeight();
if (mShader == null) return;
super.onDraw(canvas);
mPaint.setShader(mShader);
mPaint.setXfermode(DST_IN);
canvas.drawRect(0, 0, width, height, mPaint);
}
@SuppressLint("DrawAllocation")
@Override @Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final int width = MeasureSpec.getSize(widthMeasureSpec), height = width / 3; final int width = MeasureSpec.getSize(widthMeasureSpec), height = width / 2;
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
if (width > 0) {
mShader = new LinearGradient(width / 2, 0, width / 2, height, COLORS, POSITIONS, Shader.TileMode.CLAMP);
}
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
} }
@ -124,4 +106,16 @@ public class ProfileBannerImageView extends ForegroundImageView implements IExte
} }
} }
@Override
protected void dispatchDraw(final Canvas canvas) {
super.dispatchDraw(canvas);
if (mBottomClip != 0) {
canvas.drawRect(getLeft(), getBottom() - mBottomClip - getTranslationY(), getRight(), getBottom(), mClipPaint);
}
}
public void setBottomClip(int bottom) {
mBottomClip = bottom;
invalidate();
}
} }

View File

@ -34,6 +34,7 @@ public class AccountViewHolder {
public final CheckBox checkbox; public final CheckBox checkbox;
private final ColorLabelRelativeLayout content; private final ColorLabelRelativeLayout content;
private final View default_indicator; private final View default_indicator;
private final View drag_handle;
public AccountViewHolder(final View view) { public AccountViewHolder(final View view) {
content = (ColorLabelRelativeLayout) view; content = (ColorLabelRelativeLayout) view;
@ -42,12 +43,17 @@ public class AccountViewHolder {
profile_image = (ImageView) view.findViewById(android.R.id.icon); profile_image = (ImageView) view.findViewById(android.R.id.icon);
default_indicator = view.findViewById(R.id.default_indicator); default_indicator = view.findViewById(R.id.default_indicator);
checkbox = (CheckBox) view.findViewById(android.R.id.checkbox); checkbox = (CheckBox) view.findViewById(android.R.id.checkbox);
drag_handle = view.findViewById(R.id.drag_handle);
} }
public void setAccountColor(final int color) { public void setAccountColor(final int color) {
content.drawEnd(color); content.drawEnd(color);
} }
public void setSortEnabled(boolean enabled) {
drag_handle.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
public void setIsDefault(final boolean is_default) { public void setIsDefault(final boolean is_default) {
default_indicator.setVisibility(is_default ? View.VISIBLE : View.GONE); default_indicator.setVisibility(is_default ? View.VISIBLE : View.GONE);
} }

View File

@ -19,11 +19,13 @@
package org.mariotaku.twidere.view.iface; package org.mariotaku.twidere.view.iface;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
@ -47,7 +49,6 @@ public interface IForegroundView {
* the padding area. * the padding area.
* *
* @param drawable The Drawable to be drawn on top of the children. * @param drawable The Drawable to be drawn on top of the children.
*
* @attr ref android.R.attr#foreground * @attr ref android.R.attr#foreground
*/ */
public void setForeground(final Drawable drawable); public void setForeground(final Drawable drawable);
@ -56,7 +57,6 @@ public interface IForegroundView {
* Describes how the foreground is positioned. Defaults to START and TOP. * Describes how the foreground is positioned. Defaults to START and TOP.
* *
* @param foregroundGravity See {@link android.view.Gravity} * @param foregroundGravity See {@link android.view.Gravity}
*
* @attr ref android.R.attr#foregroundGravity * @attr ref android.R.attr#foregroundGravity
*/ */
public void setForegroundGravity(int foregroundGravity); public void setForegroundGravity(int foregroundGravity);
@ -76,8 +76,8 @@ public interface IForegroundView {
public ForegroundViewHelper(final View view, final Context context, final AttributeSet attrs, final int defStyle) { public ForegroundViewHelper(final View view, final Context context, final AttributeSet attrs, final int defStyle) {
mView = view; mView = view;
final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.foreground, final TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.foreground,
android.R.attr.foregroundGravity }, defStyle, 0); android.R.attr.foregroundGravity}, defStyle, 0);
mForegroundGravity = a.getInt(1, mForegroundGravity); mForegroundGravity = a.getInt(1, mForegroundGravity);
@ -225,5 +225,11 @@ public interface IForegroundView {
public boolean verifyDrawable(final Drawable who) { public boolean verifyDrawable(final Drawable who) {
return who == mForeground; return who == mForeground;
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void dispatchDrawableHotspotChanged(float x, float y) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
mForeground.setHotspot(x, y);
}
} }
} }

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" <merge xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:app="http://schemas.android.com/apk/res-auto">
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -28,7 +27,7 @@
android:hint="@string/username" android:hint="@string/username"
android:inputType="textEmailAddress" android:inputType="textEmailAddress"
android:singleLine="true" android:singleLine="true"
android:typeface="normal" /> android:typeface="normal"/>
<EditText <EditText
android:id="@+id/password" android:id="@+id/password"
@ -39,7 +38,7 @@
android:hint="@string/password" android:hint="@string/password"
android:inputType="textPassword" android:inputType="textPassword"
android:singleLine="true" android:singleLine="true"
android:typeface="normal" /> android:typeface="normal"/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -58,7 +57,7 @@
android:layout_weight="1" android:layout_weight="1"
android:minHeight="48dp" android:minHeight="48dp"
android:onClick="onClick" android:onClick="onClick"
android:text="@string/sign_in" /> android:text="@string/sign_in"/>
<Button <Button
android:id="@+id/sign_up" android:id="@+id/sign_up"
@ -68,7 +67,7 @@
android:layout_weight="1" android:layout_weight="1"
android:minHeight="48dp" android:minHeight="48dp"
android:onClick="onClick" android:onClick="onClick"
android:text="@string/sign_up" /> android:text="@string/sign_up"/>
</LinearLayout> </LinearLayout>
<Button <Button
@ -83,18 +82,8 @@
android:minHeight="36dp" android:minHeight="36dp"
android:onClick="onClick" android:onClick="onClick"
android:text="@string/sign_in_method_introduction_title" android:text="@string/sign_in_method_introduction_title"
android:textAppearance="?android:textAppearanceSmall" /> android:textAppearance="?android:textAppearanceSmall"/>
</RelativeLayout> </RelativeLayout>
</ScrollView> </ScrollView>
<ImageButton
android:id="@+id/set_color"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="bottom|right"
android:layout_weight="0"
android:contentDescription="@string/set_color"
android:onClick="onClick"
android:src="@drawable/ic_action_color_palette" />
</merge> </merge>

View File

@ -18,8 +18,10 @@
android:layout_weight="0" android:layout_weight="0"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="@dimen/element_spacing_normal"> android:paddingLeft="@dimen/element_spacing_large"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_normal"
android:paddingBottom="@dimen/element_spacing_normal">
<SeekBar <SeekBar
android:id="@+id/alpha_slider" android:id="@+id/alpha_slider"

View File

@ -9,7 +9,7 @@
android:id="@+id/left_drawer" android:id="@+id/left_drawer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
class="org.mariotaku.twidere.fragment.support.AccountsDrawerFragment" class="org.mariotaku.twidere.fragment.support.AccountsDashboardFragment"
tools:layout="@layout/fragment_accounts_drawer"/> tools:layout="@layout/fragment_accounts_drawer"/>
</org.mariotaku.twidere.view.LeftDrawerFrameLayout> </org.mariotaku.twidere.view.LeftDrawerFrameLayout>

View File

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/header_user_profile" android:id="@+id/header_user_profile"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<org.mariotaku.twidere.view.HalfWidthSpace <Space
android:id="@+id/profile_banner_space" android:id="@+id/profile_banner_space"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
@ -16,14 +17,13 @@
android:layout_height="@dimen/element_spacing_xsmall" android:layout_height="@dimen/element_spacing_xsmall"
android:layout_above="@+id/profile_name_container" android:layout_above="@+id/profile_name_container"
android:background="@drawable/shadow_top"/> android:background="@drawable/shadow_top"/>
<!--
<View <!--<View-->
android:id="@+id/profile_layer_bottom" <!--android:id="@+id/profile_layer_bottom"-->
android:layout_width="match_parent" <!--android:layout_width="match_parent"-->
android:layout_height="match_parent" <!--android:layout_height="match_parent"-->
android:layout_alignBottom="@+id/card" <!--android:layout_alignBottom="@+id/card"-->
android:layout_alignTop="@+id/profile_name_container"/> <!--android:layout_alignTop="@+id/profile_name_container"/>-->
-->
<FrameLayout <FrameLayout
android:id="@+id/profile_image_container" android:id="@+id/profile_image_container"

View File

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.mariotaku.twidere.view.ProfileBannerImageView xmlns:android="http://schemas.android.com/apk/res/android" <org.mariotaku.twidere.view.ProfileBannerImageView
android:id="@+id/profile_banner" android:id="@+id/profile_banner"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top" android:layout_gravity="top"
android:foreground="@drawable/shadow_bottom"
android:scaleType="centerCrop"/> android:scaleType="centerCrop"/>

View File

@ -26,10 +26,11 @@
android:text="@string/api_url_format" android:text="@string/api_url_format"
android:textAppearance="?android:attr/textAppearanceSmall"/> android:textAppearance="?android:attr/textAppearanceSmall"/>
<ImageButton <org.mariotaku.twidere.view.ActionIconView
android:id="@+id/api_url_format_help" android:id="@+id/api_url_format_help"
android:layout_width="@dimen/element_size_small" android:layout_width="@dimen/element_size_small"
android:layout_height="@dimen/element_size_small" android:layout_height="@dimen/element_size_small"
android:src="@drawable/ic_action_info"
android:layout_weight="0" android:layout_weight="0"
android:background="?android:selectableItemBackground"/> android:background="?android:selectableItemBackground"/>
</LinearLayout> </LinearLayout>

View File

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <org.mariotaku.twidere.view.AssetFontTextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:text="- Mea est luna -" android:layout_height="wrap_content"
android:gravity="center"
android:textColor="?android:textColorPrimary"
android:alpha="0.2" android:alpha="0.2"
android:textSize="8sp" app:fontPath="fonts/LibreBaskerville-Italic.ttf"
android:typeface="serif" android:gravity="center"
android:padding="@dimen/element_spacing_small"
android:text="- Mea est luna -"
android:textColor="?android:textColorPrimary"
android:textSize="10sp"
android:textStyle="italic" android:textStyle="italic"
android:layout_height="wrap_content" /> android:typeface="serif"/>

View File

@ -67,7 +67,6 @@
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"/> android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView <TextView
android:id="@+id/default_indicator" android:id="@+id/default_indicator"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
android:gravity="center"
android:orientation="horizontal">
<Switch
android:id="@android:id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
android:layout_width="1dp"
android:layout_height="@dimen/element_size_normal"
android:layout_marginLeft="@dimen/element_spacing_small"
android:layout_marginRight="@dimen/element_spacing_small"
android:background="?android:dividerHorizontal"/>
<org.mariotaku.twidere.view.ActionIconButton
android:id="@+id/settings"
android:layout_width="@dimen/element_size_normal"
android:layout_height="@dimen/element_size_normal"
android:background="?android:selectableItemBackground"
android:src="@drawable/ic_action_settings"/>
</LinearLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/set_as_default"
android:icon="@drawable/ic_action_checked"
android:title="@string/set_as_default"/>
<item
android:id="@id/set_color"
android:icon="@drawable/ic_action_color_palette"
android:title="@string/set_color"/>
<item
android:id="@id/delete"
android:icon="@drawable/ic_action_delete"
android:title="@string/delete"/>
</menu>

View File

@ -2,73 +2,76 @@
<resources> <resources>
<declare-styleable name="Twidere"> <declare-styleable name="Twidere">
<attr name="cardItemBackground" format="reference" /> <attr name="cardItemBackground" format="reference"/>
<attr name="cardItemBackgroundColor" format="color" /> <attr name="cardItemBackgroundColor" format="color"/>
<attr name="cardItemMessageIncomingBackground" format="reference" /> <attr name="cardItemMessageIncomingBackground" format="reference"/>
<attr name="cardItemMessageOutgoingBackground" format="reference" /> <attr name="cardItemMessageOutgoingBackground" format="reference"/>
<attr name="cardItemMessageProfileImageIncomingBackground" format="reference" /> <attr name="cardItemMessageProfileImageIncomingBackground" format="reference"/>
<attr name="cardItemMessageProfileImageOutgoingBackground" format="reference" /> <attr name="cardItemMessageProfileImageOutgoingBackground" format="reference"/>
<attr name="listMenuOverflowButton" format="reference" /> <attr name="listMenuOverflowButton" format="reference"/>
<attr name="ignorePadding" format="boolean" /> <attr name="ignorePadding" format="boolean"/>
<attr name="linePageIndicatorStyle" format="reference" /> <attr name="linePageIndicatorStyle" format="reference"/>
<attr name="cardItemViewStyle" format="reference" /> <attr name="cardItemViewStyle" format="reference"/>
<attr name="staggeredGridViewStyle" format="reference" /> <attr name="staggeredGridViewStyle" format="reference"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="CardItemView"> <declare-styleable name="CardItemView">
<attr name="cardBackground" format="reference" /> <attr name="cardBackground" format="reference"/>
<attr name="cardSelector" format="reference" /> <attr name="cardSelector" format="reference"/>
<attr name="cardActivatedIndicator" format="reference" /> <attr name="cardActivatedIndicator" format="reference"/>
<attr name="cardOverflowIcon" format="reference" /> <attr name="cardOverflowIcon" format="reference"/>
<attr name="cardBackgroundAlpha" format="fraction" /> <attr name="cardBackgroundAlpha" format="fraction"/>
<attr name="cardGapHeight" format="dimension" /> <attr name="cardGapHeight" format="dimension"/>
<attr name="cardGapText" format="string" /> <attr name="cardGapText" format="string"/>
<attr name="cardGapTextColor" format="color" /> <attr name="cardGapTextColor" format="color"/>
<attr name="cardGapTextSize" format="dimension" /> <attr name="cardGapTextSize" format="dimension"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="TabPagerIndicator"> <declare-styleable name="TabPagerIndicator">
<attr name="tabItemStyle" format="reference" /> <attr name="tabItemStyle" format="reference"/>
<attr name="tabItemContentStyle" format="reference" /> <attr name="tabItemContentStyle" format="reference"/>
<attr name="tabItemTextStyle" format="reference" /> <attr name="tabItemTextStyle" format="reference"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="LinePageIndicator"> <declare-styleable name="LinePageIndicator">
<!-- Whether or not the indicators should be centered. --> <!-- Whether or not the indicators should be centered. -->
<attr name="centered" format="boolean" /> <attr name="centered" format="boolean"/>
<!-- Color of the unselected lines that represent the pages. --> <!-- Color of the unselected lines that represent the pages. -->
<attr name="unselectedColor" format="color" /> <attr name="unselectedColor" format="color"/>
<!-- Color of the selected line that represents the current page. --> <!-- Color of the selected line that represents the current page. -->
<attr name="selectedColor" format="color" /> <attr name="selectedColor" format="color"/>
<!-- Width of each indicator line. --> <!-- Width of each indicator line. -->
<attr name="lineWidth" format="dimension" /> <attr name="lineWidth" format="dimension"/>
<!-- Width of each indicator line's stroke. --> <!-- Width of each indicator line's stroke. -->
<attr name="strokeWidth" format="dimension" /> <attr name="strokeWidth" format="dimension"/>
<!-- Width of the gap between each indicator line. --> <!-- Width of the gap between each indicator line. -->
<attr name="gapWidth" format="dimension" /> <attr name="gapWidth" format="dimension"/>
<!-- View background --> <!-- View background -->
<attr name="android:background" /> <attr name="android:background"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="ValueDependencyPreference"> <declare-styleable name="ValueDependencyPreference">
<attr name="dependencyKey" format="string" /> <attr name="dependencyKey" format="string"/>
<attr name="dependencyValues" format="reference" /> <attr name="dependencyValues" format="reference"/>
<attr name="dependencyValueDefault" format="string" /> <attr name="dependencyValueDefault" format="string"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="AccountsListPreference"> <declare-styleable name="AccountsListPreference">
<attr name="switchKey" format="string" /> <attr name="switchKey" format="string"/>
<attr name="switchDefault" format="boolean" /> <attr name="switchDefault" format="boolean"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="NotificationTypePreference"> <declare-styleable name="NotificationTypePreference">
<attr name="notificationType" /> <attr name="notificationType"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="SeekBarDialogPreference"> <declare-styleable name="SeekBarDialogPreference">
<attr name="max" format="integer" /> <attr name="max" format="integer"/>
<attr name="min" format="integer" /> <attr name="min" format="integer"/>
<attr name="progressTextSuffix" format="string" /> <attr name="step" format="integer"/>
<attr name="progressTextSuffix" format="string"/>
</declare-styleable>
<declare-styleable name="AssetFontTextView">
<attr name="fontPath" format="string"/>
</declare-styleable> </declare-styleable>
<attr name="notificationType"> <attr name="notificationType">
<flag name="none" value="0" /> <flag name="none" value="0"/>
<flag name="ringtone" value="1" /> <flag name="ringtone" value="1"/>
<flag name="vibration" value="2" /> <flag name="vibration" value="2"/>
<flag name="light" value="4" /> <flag name="light" value="4"/>
</attr> </attr>
</resources> </resources>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="settings_content" android:key="settings_content"
android:title="@string/content_and_storage"> android:title="@string/content_and_storage">
@ -72,7 +73,8 @@
android:summary="@string/load_item_limit_summary" android:summary="@string/load_item_limit_summary"
android:title="@string/load_item_limit" android:title="@string/load_item_limit"
app:max="200" app:max="200"
app:min="10"/> app:min="10"
app:step="5"/>
<org.mariotaku.twidere.preference.TimelineSyncPreference <org.mariotaku.twidere.preference.TimelineSyncPreference
android:defaultValue="" android:defaultValue=""