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());
try { if (bm == null) return profileBackgroundColor;
final String profileBackgroundColor = user.getProfileBackgroundColor();
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 { try {
return ColorAnalyser.analyse(bm); return Palette.generate(bm).getVibrantColor(profileBackgroundColor);
} 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);
} }
mAdapter.add(new MediaTimelineAction(1)); if (Utils.isOfficialKeyAccount(getActivity(), user.account_id)) {
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,180 +56,175 @@ 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;
public AccountsListPreference(final Context context) { public AccountsListPreference(final Context context) {
this(context, null); this(context, null);
} }
public AccountsListPreference(final Context context, final AttributeSet attrs) { public AccountsListPreference(final Context context, final AttributeSet attrs) {
this(context, attrs, android.R.attr.preferenceCategoryStyle); this(context, attrs, android.R.attr.preferenceCategoryStyle);
} }
public AccountsListPreference(final Context context, final AttributeSet attrs, final int defStyle) { public AccountsListPreference(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS); final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
mSwitchKey = a.getString(0); mSwitchKey = a.getString(0);
mSwitchDefault = a.getBoolean(1, false); mSwitchDefault = a.getBoolean(1, false);
a.recycle(); a.recycle();
} }
public void setAccountsData(final List<Account> accounts) { public void setAccountsData(final List<Account> accounts) {
removeAll(); removeAll();
for (final Account account : accounts) { for (final Account account : accounts) {
final AccountItemPreference preference = new AccountItemPreference(getContext(), account, mSwitchKey, final AccountItemPreference preference = new AccountItemPreference(getContext(), account, mSwitchKey,
mSwitchDefault); mSwitchDefault);
setupPreference(preference, account); setupPreference(preference, account);
addPreference(preference); addPreference(preference);
} }
final Preference preference = new Preference(getContext()); final Preference preference = new Preference(getContext());
preference.setLayoutResource(R.layout.settings_layout_click_to_config); preference.setLayoutResource(R.layout.settings_layout_click_to_config);
addPreference(preference); addPreference(preference);
} }
@Override @Override
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) { protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) {
super.onAttachedToHierarchy(preferenceManager); super.onAttachedToHierarchy(preferenceManager);
new LoadAccountsTask(this).execute(); new LoadAccountsTask(this).execute();
} }
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,
final boolean switchDefault) {
super(context);
setWidgetLayoutResource(R.layout.preference_widget_account_preference_item);
setOnPreferenceClickListener(this);
final String switchPreferenceName = ACCOUNT_PREFERENCES_NAME_PREFIX + account.account_id;
mAccount = account;
mSwitchPreference = context.getSharedPreferences(switchPreferenceName, Context.MODE_PRIVATE);
mSwitchKey = switchKey;
mSwitchDefault = switchDefault;
mSwitchPreference.registerOnSharedPreferenceChangeListener(this);
}
public AccountItemPreference(final Context context, final Account account, final String switchKey, @Override
final boolean switchDefault) { public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
super(context); if (mSwitchKey == null) return;
final String switchPreferenceName = ACCOUNT_PREFERENCES_NAME_PREFIX + account.account_id; final SharedPreferences.Editor editor = mSwitchPreference.edit();
mAccount = account; editor.putBoolean(mSwitchKey, isChecked);
mDensity = context.getResources().getDisplayMetrics().density; editor.apply();
mSwitchPreference = context.getSharedPreferences(switchPreferenceName, Context.MODE_PRIVATE); }
mSwitchKey = switchKey;
mSwitchDefault = switchDefault;
mSwitchPreference.registerOnSharedPreferenceChangeListener(this);
}
@Override @Override
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { public void onLoadingCancelled(final String imageUri, final View view) {
if (mSwitchKey == null) return; setIcon(R.drawable.ic_profile_image_default);
final SharedPreferences.Editor editor = mSwitchPreference.edit(); }
editor.putBoolean(mSwitchKey, isChecked);
editor.apply();
}
@Override @Override
public void onLoadingCancelled(final String imageUri, final View view) { public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) {
setIcon(R.drawable.ic_profile_image_default); setIcon(new BitmapDrawable(getContext().getResources(), loadedImage));
} }
@Override @Override
public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) { public void onLoadingFailed(final String imageUri, final View view, final FailReason failReason) {
setIcon(new BitmapDrawable(getContext().getResources(), loadedImage)); setIcon(R.drawable.ic_profile_image_default);
} }
@Override @Override
public void onLoadingFailed(final String imageUri, final View view, final FailReason failReason) { public void onLoadingStarted(final String imageUri, final View view) {
setIcon(R.drawable.ic_profile_image_default); setIcon(R.drawable.ic_profile_image_default);
} }
@Override @Override
public void onLoadingStarted(final String imageUri, final View view) { public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
setIcon(R.drawable.ic_profile_image_default); notifyChanged();
} }
@Override @Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) { protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) {
updateSwitchState(); super.onAttachedToHierarchy(preferenceManager);
} setTitle(mAccount.name);
setSummary(String.format("@%s", mAccount.screen_name));
setIcon(R.drawable.ic_profile_image_default);
final TwidereApplication app = TwidereApplication.getInstance(getContext());
final ImageLoaderWrapper loader = app.getImageLoaderWrapper();
loader.loadProfileImage(mAccount.profile_image_url, this);
}
@Override @Override
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) { protected View onCreateView(ViewGroup parent) {
super.onAttachedToHierarchy(preferenceManager); final View view = super.onCreateView(parent);
setTitle(mAccount.name); view.findViewById(R.id.settings).setOnClickListener(this);
setSummary(String.format("@%s", mAccount.screen_name)); final Switch toggle = (Switch) view.findViewById(android.R.id.toggle);
setIcon(R.drawable.ic_profile_image_default); toggle.setOnCheckedChangeListener(this);
final TwidereApplication app = TwidereApplication.getInstance(getContext()); return view;
final ImageLoaderWrapper loader = app.getImageLoaderWrapper(); }
loader.loadProfileImage(mAccount.profile_image_url, this);
}
@Override @Override
protected void onBindView(final View view) { 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); }
} final View titleView = view.findViewById(android.R.id.title);
final View titleView = view.findViewById(android.R.id.title); if (titleView instanceof TextView) {
if (titleView instanceof TextView) { ((TextView) titleView).setSingleLine(true);
((TextView) titleView).setSingleLine(true); }
} final View summaryView = view.findViewById(android.R.id.summary);
final View summaryView = view.findViewById(android.R.id.summary); if (summaryView instanceof TextView) {
if (summaryView instanceof TextView) { ((TextView) summaryView).setSingleLine(true);
((TextView) summaryView).setSingleLine(true); }
} final Switch toggle = (Switch) view.findViewById(android.R.id.toggle);
updateSwitchState(); if (mSwitchKey != null) {
} toggle.setChecked(mSwitchPreference.getBoolean(mSwitchKey, mSwitchDefault));
}
}
private void updateSwitchState() { @Override
if (mView == null) return; public boolean onPreferenceClick(Preference preference) {
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) {
toggle.setChecked(mSwitchPreference.getBoolean(mSwitchKey, mSwitchDefault));
}
}
} return true;
}
private static class LoadAccountsTask extends AsyncTask<Void, Void, List<Account>> { @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 final AccountsListPreference mPreference; private static class LoadAccountsTask extends AsyncTask<Void, Void, List<Account>> {
public LoadAccountsTask(final AccountsListPreference preference) { private final AccountsListPreference mPreference;
mPreference = preference;
}
@Override public LoadAccountsTask(final AccountsListPreference preference) {
protected List<Account> doInBackground(final Void... params) { mPreference = preference;
return Account.getAccountsList(mPreference.getContext(), false); }
}
@Override @Override
protected void onPostExecute(final List<Account> result) { protected List<Account> doInBackground(final Void... params) {
mPreference.setAccountsData(result); return Account.getAccountsList(mPreference.getContext(), false);
} }
} @Override
protected void onPostExecute(final List<Account> result) {
mPreference.setAccountsData(result);
}
}
} }

View File

@ -36,219 +36,238 @@ import org.mariotaku.twidere.R;
/** /**
* A {@link DialogPreference} that provides a user with the means to select an * A {@link DialogPreference} that provides a user with the means to select an
* integer from a {@link SeekBar}, and persist it. * integer from a {@link SeekBar}, and persist it.
* *
* @author lukehorvat * @author lukehorvat
*/ */
public class SeekBarDialogPreference extends DialogPreference { 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 CharSequence mProgressTextSuffix; private int mStep;
private TextView mProgressText;
private SeekBar mSeekBar;
public SeekBarDialogPreference(final Context context) { private CharSequence mProgressTextSuffix;
this(context, null); private TextView mProgressText;
} private SeekBar mSeekBar;
public SeekBarDialogPreference(final Context context, final AttributeSet attrs) { public SeekBarDialogPreference(final Context context) {
this(context, attrs, android.R.attr.dialogPreferenceStyle); this(context, null);
} }
public SeekBarDialogPreference(final Context context, final AttributeSet attrs, final int defStyle) { public SeekBarDialogPreference(final Context context, final AttributeSet attrs) {
super(context, attrs, defStyle); this(context, attrs, android.R.attr.dialogPreferenceStyle);
}
// get attributes specified in XML public SeekBarDialogPreference(final Context context, final AttributeSet attrs, final int defStyle) {
final TypedArray a = context.getTheme() super(context, attrs, defStyle);
.obtainStyledAttributes(attrs, R.styleable.SeekBarDialogPreference, 0, 0);
try {
setMinProgress(a.getInteger(R.styleable.SeekBarDialogPreference_min, DEFAULT_MIN_PROGRESS));
setMaxProgress(a.getInteger(R.styleable.SeekBarDialogPreference_max, DEFAULT_MAX_PROGRESS));
setProgressTextSuffix(a.getString(R.styleable.SeekBarDialogPreference_progressTextSuffix));
} finally {
a.recycle();
}
// set layout // get attributes specified in XML
setDialogLayoutResource(R.layout.preference_seek_bar_dialog); final TypedArray a = context.getTheme()
setPositiveButtonText(android.R.string.ok); .obtainStyledAttributes(attrs, R.styleable.SeekBarDialogPreference, 0, 0);
setNegativeButtonText(android.R.string.cancel); try {
setDialogIcon(null); setMinProgress(a.getInteger(R.styleable.SeekBarDialogPreference_min, DEFAULT_MIN_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));
} finally {
a.recycle();
}
public int getMaxProgress() { // set layout
return mMaxProgress; setDialogLayoutResource(R.layout.preference_seek_bar_dialog);
} setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
setDialogIcon(null);
}
public int getMinProgress() { public void setStep(int step) {
return mMinProgress; mStep = step;
} }
public int getProgress() { public int getMaxProgress() {
return mProgress; return mMaxProgress;
} }
public CharSequence getProgressTextSuffix() { public int getMinProgress() {
return mProgressTextSuffix; return mMinProgress;
} }
public void setMaxProgress(final int maxProgress) { public int getProgress() {
mMaxProgress = maxProgress; return mProgress;
setProgress(Math.min(mProgress, mMaxProgress)); }
}
public void setMinProgress(final int minProgress) { public CharSequence getProgressTextSuffix() {
mMinProgress = minProgress; return mProgressTextSuffix;
setProgress(Math.max(mProgress, mMinProgress)); }
}
public void setProgress(int progress) { public void setMaxProgress(final int maxProgress) {
progress = Math.max(Math.min(progress, mMaxProgress), mMinProgress); mMaxProgress = maxProgress;
setProgress(Math.min(mProgress, mMaxProgress));
}
if (progress != mProgress) { public void setMinProgress(final int minProgress) {
mProgress = progress; mMinProgress = minProgress;
persistInt(progress); setProgress(Math.max(mProgress, mMinProgress));
notifyChanged(); }
}
}
public void setProgressTextSuffix(final CharSequence progressTextSuffix) { /**
mProgressTextSuffix = progressTextSuffix; * @param progress Real progress multiplied by steps
} */
public void setProgress(int progress) {
progress = Math.max(Math.min(progress, mMaxProgress), mMinProgress);
@Override if (progress != mProgress) {
protected void onBindDialogView(final View view) { mProgress = progress;
super.onBindDialogView(view); persistInt(progress);
notifyChanged();
}
}
final CharSequence message = getDialogMessage(); public void setProgressTextSuffix(final CharSequence progressTextSuffix) {
final TextView dialogMessageText = (TextView) view.findViewById(R.id.text_dialog_message); mProgressTextSuffix = progressTextSuffix;
dialogMessageText.setText(message); }
dialogMessageText.setVisibility(TextUtils.isEmpty(message) ? View.GONE : View.VISIBLE);
mProgressText = (TextView) view.findViewById(R.id.text_progress); @Override
protected void onBindDialogView(final View view) {
super.onBindDialogView(view);
mSeekBar = (SeekBar) view.findViewById(R.id.seek_bar); final CharSequence message = getDialogMessage();
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { final TextView dialogMessageText = (TextView) view.findViewById(R.id.text_dialog_message);
@Override dialogMessageText.setText(message);
public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) { dialogMessageText.setVisibility(TextUtils.isEmpty(message) ? View.GONE : View.VISIBLE);
// update text that displays the current SeekBar progress value
// note: this does not persist the progress value. that is only
// ever done in setProgress()
final String progressStr = String.valueOf(progress + mMinProgress);
mProgressText.setText(mProgressTextSuffix == null ? progressStr : progressStr
.concat(mProgressTextSuffix.toString()));
}
@Override mProgressText = (TextView) view.findViewById(R.id.text_progress);
public void onStartTrackingTouch(final SeekBar seekBar) {
}
@Override mSeekBar = (SeekBar) view.findViewById(R.id.seek_bar);
public void onStopTrackingTouch(final SeekBar seekBar) { mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
} @Override
}); public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
mSeekBar.setMax(mMaxProgress - mMinProgress); // update text that displays the current SeekBar progress value
mSeekBar.setProgress(mProgress - mMinProgress); // note: this does not persist the progress value. that is only
} // ever done in setProgress()
final String progressStr = String.valueOf(progress * mStep + mMinProgress);
mProgressText.setText(mProgressTextSuffix == null ? progressStr : progressStr
.concat(mProgressTextSuffix.toString()));
}
@Override @Override
protected void onDialogClosed(final boolean positiveResult) { public void onStartTrackingTouch(final SeekBar seekBar) {
super.onDialogClosed(positiveResult); }
// when the user selects "OK", persist the new value @Override
if (positiveResult) { public void onStopTrackingTouch(final SeekBar seekBar) {
final int seekBarProgress = mSeekBar.getProgress() + mMinProgress; }
if (callChangeListener(seekBarProgress)) { });
setProgress(seekBarProgress); mSeekBar.setMax((int) Math.ceil((mMaxProgress - mMinProgress) / (double) mStep));
} mSeekBar.setProgress((int) Math.ceil((mProgress - mMinProgress) / (double) mStep));
} }
}
@Override @Override
protected Object onGetDefaultValue(final TypedArray a, final int index) { protected void onDialogClosed(final boolean positiveResult) {
return a.getInt(index, DEFAULT_PROGRESS); super.onDialogClosed(positiveResult);
}
@Override // when the user selects "OK", persist the new value
protected void onRestoreInstanceState(final Parcelable state) { if (positiveResult) {
// check whether we saved the state in onSaveInstanceState() final int realProgress = mSeekBar.getProgress() * mStep + mMinProgress;
if (state == null || !state.getClass().equals(SavedState.class)) { if (callChangeListener(realProgress)) {
// didn't save the state, so call superclass setProgress(realProgress);
super.onRestoreInstanceState(state); }
return; }
} }
// restore the state @Override
final SavedState myState = (SavedState) state; protected Object onGetDefaultValue(final TypedArray a, final int index) {
setMinProgress(myState.minProgress); return a.getInt(index, DEFAULT_PROGRESS);
setMaxProgress(myState.maxProgress); }
setProgress(myState.progress);
super.onRestoreInstanceState(myState.getSuperState()); @Override
} protected void onRestoreInstanceState(final Parcelable state) {
// check whether we saved the state in onSaveInstanceState()
if (state == null || !state.getClass().equals(SavedState.class)) {
// didn't save the state, so call superclass
super.onRestoreInstanceState(state);
return;
}
@Override // restore the state
protected Parcelable onSaveInstanceState() { final SavedState myState = (SavedState) state;
// save the instance state so that it will survive screen orientation setMinProgress(myState.minProgress);
// changes and other events that may temporarily destroy it setMaxProgress(myState.maxProgress);
final Parcelable superState = super.onSaveInstanceState(); setProgress(myState.progress);
setStep(myState.step);
// set the state's value with the class member that holds current super.onRestoreInstanceState(myState.getSuperState());
// setting value }
final SavedState myState = new SavedState(superState);
myState.minProgress = getMinProgress();
myState.maxProgress = getMaxProgress();
myState.progress = getProgress();
return myState; @Override
} protected Parcelable onSaveInstanceState() {
// save the instance state so that it will survive screen orientation
// changes and other events that may temporarily destroy it
final Parcelable superState = super.onSaveInstanceState();
@Override // set the state's value with the class member that holds current
protected void onSetInitialValue(final boolean restore, final Object defaultValue) { // setting value
setProgress(restore ? getPersistedInt(DEFAULT_PROGRESS) : (Integer) defaultValue); final SavedState myState = new SavedState(superState);
} myState.minProgress = getMinProgress();
myState.maxProgress = getMaxProgress();
myState.progress = getProgress();
myState.step = getStep();
return myState;
}
private static class SavedState extends BaseSavedState { private int getStep() {
int minProgress; return mStep;
int maxProgress; }
int progress;
@SuppressWarnings("unused") @Override
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { protected void onSetInitialValue(final boolean restore, final Object defaultValue) {
@Override setProgress(restore ? getPersistedInt(DEFAULT_PROGRESS) : (Integer) defaultValue);
public SavedState createFromParcel(final Parcel in) { }
return new SavedState(in);
}
@Override private static class SavedState extends BaseSavedState {
public SavedState[] newArray(final int size) { int minProgress;
return new SavedState[size]; int maxProgress;
} int progress;
}; int step;
public SavedState(final Parcel source) { @SuppressWarnings("unused")
super(source); public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(final Parcel in) {
return new SavedState(in);
}
minProgress = source.readInt(); @Override
maxProgress = source.readInt(); public SavedState[] newArray(final int size) {
progress = source.readInt(); return new SavedState[size];
} }
};
public SavedState(final Parcelable superState) { public SavedState(final Parcel source) {
super(superState); super(source);
}
@Override minProgress = source.readInt();
public void writeToParcel(final Parcel dest, final int flags) { maxProgress = source.readInt();
super.writeToParcel(dest, flags); progress = source.readInt();
step = source.readInt();
}
dest.writeInt(minProgress); public SavedState(final Parcelable superState) {
dest.writeInt(maxProgress); super(superState);
dest.writeInt(progress); }
}
} @Override
public void writeToParcel(final Parcel dest, final int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(minProgress);
dest.writeInt(maxProgress);
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;
@ -29,86 +31,91 @@ import org.mariotaku.twidere.view.iface.IForegroundView;
public class ForegroundImageView extends ImageView implements IForegroundView { public class ForegroundImageView extends ImageView implements IForegroundView {
private final ForegroundViewHelper mForegroundViewHelper; private final ForegroundViewHelper mForegroundViewHelper;
public ForegroundImageView(final Context context) { public ForegroundImageView(final Context context) {
this(context, null); this(context, null);
} }
public ForegroundImageView(final Context context, final AttributeSet attrs) { public ForegroundImageView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0); this(context, attrs, 0);
} }
public ForegroundImageView(final Context context, final AttributeSet attrs, final int defStyle) { public ForegroundImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
mForegroundViewHelper = new ForegroundViewHelper(this, context, attrs, defStyle); mForegroundViewHelper = new ForegroundViewHelper(this, context, attrs, defStyle);
} }
@Override @Override
public Drawable getForeground() { public Drawable getForeground() {
return mForegroundViewHelper.getForeground(); return mForegroundViewHelper.getForeground();
} }
@Override @TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void jumpDrawablesToCurrentState() { @Override
super.jumpDrawablesToCurrentState(); public void drawableHotspotChanged(float x, float y) {
mForegroundViewHelper.jumpDrawablesToCurrentState(); super.drawableHotspotChanged(x, y);
} mForegroundViewHelper.dispatchDrawableHotspotChanged(x, y);
}
/** @Override
* Supply a Drawable that is to be rendered on top of all of the child views public void jumpDrawablesToCurrentState() {
* in the frame layout. Any padding in the Drawable will be taken into super.jumpDrawablesToCurrentState();
* account by ensuring that the children are inset to be placed inside of mForegroundViewHelper.jumpDrawablesToCurrentState();
* the padding area. }
*
* @param drawable The Drawable to be drawn on top of the children.
*
* @attr ref android.R.styleable#FrameLayout_foreground
*/
@Override
public void setForeground(final Drawable drawable) {
mForegroundViewHelper.setForeground(drawable);
}
/** /**
* Describes how the foreground is positioned. Defaults to START and TOP. * Supply a Drawable that is to be rendered on top of all of the child views
* * in the frame layout. Any padding in the Drawable will be taken into
* @param foregroundGravity See {@link android.view.Gravity} * account by ensuring that the children are inset to be placed inside of
* * the padding area.
* @attr ref android.R.styleable#FrameLayout_foregroundGravity *
*/ * @param drawable The Drawable to be drawn on top of the children.
@Override * @attr ref android.R.styleable#FrameLayout_foreground
public void setForegroundGravity(final int foregroundGravity) { */
mForegroundViewHelper.setForegroundGravity(foregroundGravity); @Override
} public void setForeground(final Drawable drawable) {
mForegroundViewHelper.setForeground(drawable);
}
@Override /**
protected void drawableStateChanged() { * Describes how the foreground is positioned. Defaults to START and TOP.
super.drawableStateChanged(); *
mForegroundViewHelper.drawableStateChanged(); * @param foregroundGravity See {@link android.view.Gravity}
} * @attr ref android.R.styleable#FrameLayout_foregroundGravity
*/
@Override
public void setForegroundGravity(final int foregroundGravity) {
mForegroundViewHelper.setForegroundGravity(foregroundGravity);
}
@Override @Override
protected void onDraw(final Canvas canvas) { protected void drawableStateChanged() {
super.onDraw(canvas); super.drawableStateChanged();
mForegroundViewHelper.dispatchOnDraw(canvas); mForegroundViewHelper.drawableStateChanged();
} }
@Override @Override
protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) { protected void onDraw(final Canvas canvas) {
mForegroundViewHelper.dispatchOnLayout(changed, left, top, right, bottom); super.onDraw(canvas);
super.onLayout(changed, left, top, right, bottom); mForegroundViewHelper.dispatchOnDraw(canvas);
} }
@Override @Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) {
super.onSizeChanged(w, h, oldw, oldh); mForegroundViewHelper.dispatchOnLayout(changed, left, top, right, bottom);
mForegroundViewHelper.dispatchOnSizeChanged(w, h, oldw, oldh); super.onLayout(changed, left, top, right, bottom);
} }
@Override @Override
protected boolean verifyDrawable(final Drawable who) { protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
return super.verifyDrawable(who) || mForegroundViewHelper.verifyDrawable(who); super.onSizeChanged(w, h, oldw, oldh);
} mForegroundViewHelper.dispatchOnSizeChanged(w, h, oldw, oldh);
}
@Override
protected boolean verifyDrawable(final Drawable who) {
return super.verifyDrawable(who) || mForegroundViewHelper.verifyDrawable(who);
}
} }

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,91 +35,87 @@ 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 OnSizeChangedListener mOnSizeChangedListener;
private static final int[] COLORS_REVERSED = new int[] { 0x00FFFFFF, 0xFFFFFFFF }; private TouchInterceptor mTouchInterceptor;
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 final Paint mClipPaint = new Paint();
private TouchInterceptor mTouchInterceptor; private int mBottomClip;
private final Paint mPaint = new Paint(); public ProfileBannerImageView(final Context context) {
private LinearGradient mShader; this(context, null);
}
public ProfileBannerImageView(final Context context) { public ProfileBannerImageView(final Context context, final AttributeSet attrs) {
this(context, null); this(context, attrs, 0);
} }
public ProfileBannerImageView(final Context context, final AttributeSet attrs) { public ProfileBannerImageView(final Context context, final AttributeSet attrs, final int defStyle) {
this(context, attrs, 0); super(context, attrs, defStyle);
} if (isInEditMode()) return;
ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, null);
public ProfileBannerImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode()) return;
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() {
if (mTouchInterceptor != null) { return true;
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event); }
if (ret) return true;
}
return super.dispatchTouchEvent(event);
}
@Override @Override
public final boolean onTouchEvent(final MotionEvent event) { public final boolean dispatchTouchEvent(@NonNull final MotionEvent event) {
if (mTouchInterceptor != null) { if (mTouchInterceptor != null) {
final boolean ret = mTouchInterceptor.onTouchEvent(this, event); final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
if (ret) return true; if (ret) return true;
} }
return super.onTouchEvent(event); return super.dispatchTouchEvent(event);
} }
@Override @Override
public final void setOnSizeChangedListener(final OnSizeChangedListener listener) { public final boolean onTouchEvent(@NonNull final MotionEvent event) {
mOnSizeChangedListener = listener; if (mTouchInterceptor != null) {
} final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
if (ret) return true;
}
return super.onTouchEvent(event);
}
@Override @Override
public final void setTouchInterceptor(final TouchInterceptor listener) { public final void setOnSizeChangedListener(final OnSizeChangedListener listener) {
mTouchInterceptor = listener; mOnSizeChangedListener = listener;
} }
@Override @Override
protected void onDraw(final Canvas canvas) { public final void setTouchInterceptor(final TouchInterceptor listener) {
if (isInEditMode()) return; mTouchInterceptor = listener;
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 / 2;
final int width = MeasureSpec.getSize(widthMeasureSpec), height = width / 3; setMeasuredDimension(width, height);
setMeasuredDimension(width, height); super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
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));
}
@Override @Override
protected final void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { protected final void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh); super.onSizeChanged(w, h, oldw, oldh);
if (mOnSizeChangedListener != null) { if (mOnSizeChangedListener != null) {
mOnSizeChangedListener.onSizeChanged(this, w, h, oldw, oldh); mOnSizeChangedListener.onSizeChanged(this, w, h, oldw, oldh);
} }
} }
@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

@ -29,26 +29,32 @@ import org.mariotaku.twidere.view.ColorLabelRelativeLayout;
public class AccountViewHolder { public class AccountViewHolder {
public final ImageView profile_image; public final ImageView profile_image;
public final TextView name, screen_name; public final TextView name, screen_name;
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;
name = (TextView) view.findViewById(android.R.id.text1); name = (TextView) view.findViewById(android.R.id.text1);
screen_name = (TextView) view.findViewById(android.R.id.text2); screen_name = (TextView) view.findViewById(android.R.id.text2);
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 setIsDefault(final boolean is_default) { public void setSortEnabled(boolean enabled) {
default_indicator.setVisibility(is_default ? View.VISIBLE : View.GONE); drag_handle.setVisibility(enabled ? View.VISIBLE : View.GONE);
} }
public void setIsDefault(final boolean is_default) {
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;
@ -32,198 +34,202 @@ import android.view.View;
public interface IForegroundView { public interface IForegroundView {
/** /**
* Returns the drawable used as the foreground of this FrameLayout. The * Returns the drawable used as the foreground of this FrameLayout. The
* foreground drawable, if non-null, is always drawn on top of the children. * foreground drawable, if non-null, is always drawn on top of the children.
* *
* @return A Drawable or null if no foreground was set. * @return A Drawable or null if no foreground was set.
*/ */
public Drawable getForeground(); public Drawable getForeground();
/** /**
* Supply a Drawable that is to be rendered on top of all of the child views * Supply a Drawable that is to be rendered on top of all of the child views
* in the frame layout. Any padding in the Drawable will be taken into * in the frame layout. Any padding in the Drawable will be taken into
* account by ensuring that the children are inset to be placed inside of * account by ensuring that the children are inset to be placed inside of
* 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);
/** /**
* 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);
public static class ForegroundViewHelper { public static class ForegroundViewHelper {
private final View mView; private final View mView;
private final Rect mSelfBounds = new Rect(); private final Rect mSelfBounds = new Rect();
private final Rect mOverlayBounds = new Rect(); private final Rect mOverlayBounds = new Rect();
private Drawable mForeground; private Drawable mForeground;
private int mForegroundGravity = Gravity.FILL; private int mForegroundGravity = Gravity.FILL;
private boolean mForegroundInPadding = true; private boolean mForegroundInPadding = true;
private boolean mForegroundBoundsChanged = false; private boolean mForegroundBoundsChanged = false;
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);
final Drawable d = a.getDrawable(0); final Drawable d = a.getDrawable(0);
if (d != null) { if (d != null) {
setForeground(d); setForeground(d);
} }
mForegroundInPadding = true; mForegroundInPadding = true;
a.recycle(); a.recycle();
} }
public void dispatchOnDraw(final Canvas canvas) { public void dispatchOnDraw(final Canvas canvas) {
if (mForeground != null) { if (mForeground != null) {
final Drawable foreground = mForeground; final Drawable foreground = mForeground;
if (mForegroundBoundsChanged) { if (mForegroundBoundsChanged) {
mForegroundBoundsChanged = false; mForegroundBoundsChanged = false;
final Rect selfBounds = mSelfBounds; final Rect selfBounds = mSelfBounds;
final Rect overlayBounds = mOverlayBounds; final Rect overlayBounds = mOverlayBounds;
final int w = mView.getRight() - mView.getLeft(); final int w = mView.getRight() - mView.getLeft();
final int h = mView.getBottom() - mView.getTop(); final int h = mView.getBottom() - mView.getTop();
if (mForegroundInPadding) { if (mForegroundInPadding) {
selfBounds.set(0, 0, w, h); selfBounds.set(0, 0, w, h);
} else { } else {
selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h
- mView.getPaddingBottom()); - mView.getPaddingBottom());
} }
final int layoutDirection = ViewCompat.getLayoutDirection(mView); final int layoutDirection = ViewCompat.getLayoutDirection(mView);
GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(), GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection); foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection);
foreground.setBounds(overlayBounds); foreground.setBounds(overlayBounds);
} }
foreground.draw(canvas); foreground.draw(canvas);
} }
} }
public void dispatchOnLayout(final boolean changed, final int left, final int top, final int right, public void dispatchOnLayout(final boolean changed, final int left, final int top, final int right,
final int bottom) { final int bottom) {
mForegroundBoundsChanged = true; mForegroundBoundsChanged = true;
} }
public void dispatchOnSizeChanged(final int w, final int h, final int oldw, final int oldh) { public void dispatchOnSizeChanged(final int w, final int h, final int oldw, final int oldh) {
mForegroundBoundsChanged = true; mForegroundBoundsChanged = true;
} }
public void draw(final Canvas canvas) { public void draw(final Canvas canvas) {
if (mForeground != null) { if (mForeground != null) {
final Drawable foreground = mForeground; final Drawable foreground = mForeground;
if (mForegroundBoundsChanged) { if (mForegroundBoundsChanged) {
mForegroundBoundsChanged = false; mForegroundBoundsChanged = false;
final Rect selfBounds = mSelfBounds; final Rect selfBounds = mSelfBounds;
final Rect overlayBounds = mOverlayBounds; final Rect overlayBounds = mOverlayBounds;
final int w = mView.getRight() - mView.getLeft(); final int w = mView.getRight() - mView.getLeft();
final int h = mView.getBottom() - mView.getTop(); final int h = mView.getBottom() - mView.getTop();
if (mForegroundInPadding) { if (mForegroundInPadding) {
selfBounds.set(0, 0, w, h); selfBounds.set(0, 0, w, h);
} else { } else {
selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h
- mView.getPaddingBottom()); - mView.getPaddingBottom());
} }
final int layoutDirection = ViewCompat.getLayoutDirection(mView); final int layoutDirection = ViewCompat.getLayoutDirection(mView);
GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(), GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection); foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection);
foreground.setBounds(overlayBounds); foreground.setBounds(overlayBounds);
} }
foreground.draw(canvas); foreground.draw(canvas);
} }
} }
public void drawableStateChanged() { public void drawableStateChanged() {
if (mForeground != null && mForeground.isStateful()) { if (mForeground != null && mForeground.isStateful()) {
mForeground.setState(mView.getDrawableState()); mForeground.setState(mView.getDrawableState());
} }
} }
public Drawable getForeground() { public Drawable getForeground() {
return mForeground; return mForeground;
} }
public void jumpDrawablesToCurrentState() { public void jumpDrawablesToCurrentState() {
if (mForeground != null) { if (mForeground != null) {
mForeground.jumpToCurrentState(); mForeground.jumpToCurrentState();
} }
} }
public void setForeground(final Drawable drawable) { public void setForeground(final Drawable drawable) {
if (mForeground != drawable) { if (mForeground != drawable) {
if (mForeground != null) { if (mForeground != null) {
mForeground.setCallback(null); mForeground.setCallback(null);
mView.unscheduleDrawable(mForeground); mView.unscheduleDrawable(mForeground);
} }
mForeground = drawable; mForeground = drawable;
if (drawable != null) { if (drawable != null) {
drawable.setCallback(mView); drawable.setCallback(mView);
if (drawable.isStateful()) { if (drawable.isStateful()) {
drawable.setState(mView.getDrawableState()); drawable.setState(mView.getDrawableState());
} }
if (mForegroundGravity == Gravity.FILL) { if (mForegroundGravity == Gravity.FILL) {
final Rect padding = new Rect(); final Rect padding = new Rect();
if (drawable.getPadding(padding)) { if (drawable.getPadding(padding)) {
} }
} }
} }
mView.requestLayout(); mView.requestLayout();
mView.invalidate(); mView.invalidate();
} }
} }
public void setForegroundGravity(int foregroundGravity) { public void setForegroundGravity(int foregroundGravity) {
if (mForegroundGravity != foregroundGravity) { if (mForegroundGravity != foregroundGravity) {
if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
foregroundGravity |= Gravity.START; foregroundGravity |= Gravity.START;
} }
if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
foregroundGravity |= Gravity.TOP; foregroundGravity |= Gravity.TOP;
} }
mForegroundGravity = foregroundGravity; mForegroundGravity = foregroundGravity;
if (mForegroundGravity == Gravity.FILL && mForeground != null) { if (mForegroundGravity == Gravity.FILL && mForeground != null) {
final Rect padding = new Rect(); final Rect padding = new Rect();
if (mForeground.getPadding(padding)) { if (mForeground.getPadding(padding)) {
} }
} else { } else {
} }
mView.requestLayout(); mView.requestLayout();
} }
} }
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,300 +1,300 @@
<?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:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/header_user_profile" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:id="@+id/header_user_profile"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:orientation="vertical"> android:layout_height="wrap_content"
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"/>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
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
android:id="@+id/profile_layer_bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/card"
android:layout_alignTop="@+id/profile_name_container"/>
-->
<FrameLayout <!--<View-->
android:id="@+id/profile_image_container" <!--android:id="@+id/profile_layer_bottom"-->
android:layout_width="wrap_content" <!--android:layout_width="match_parent"-->
android:layout_height="wrap_content" <!--android:layout_height="match_parent"-->
android:layout_alignBottom="@+id/profile_name_container" <!--android:layout_alignBottom="@+id/card"-->
android:layout_marginLeft="@dimen/element_spacing_normal" <!--android:layout_alignTop="@+id/profile_name_container"/>-->
android:background="?cardItemBackground">
<org.mariotaku.twidere.view.ProfileImageView <FrameLayout
android:id="@+id/profile_image" android:id="@+id/profile_image_container"
android:layout_width="@dimen/icon_size_user_profile" android:layout_width="wrap_content"
android:layout_height="@dimen/icon_size_user_profile" android:layout_height="wrap_content"
android:contentDescription="@string/profile_image" android:layout_alignBottom="@+id/profile_name_container"
android:scaleType="centerCrop" android:layout_marginLeft="@dimen/element_spacing_normal"
android:src="@drawable/ic_profile_image_default"/> android:background="?cardItemBackground">
</FrameLayout>
<org.mariotaku.twidere.view.ColorLabelLinearLayout <org.mariotaku.twidere.view.ProfileImageView
android:id="@+id/profile_name_container" android:id="@+id/profile_image"
android:layout_width="match_parent" android:layout_width="@dimen/icon_size_user_profile"
android:layout_height="wrap_content" android:layout_height="@dimen/icon_size_user_profile"
android:layout_below="@+id/profile_banner_space" android:contentDescription="@string/profile_image"
android:layout_toRightOf="@+id/profile_image_container" android:scaleType="centerCrop"
android:background="?android:selectableItemBackground" android:src="@drawable/ic_profile_image_default"/>
android:clipToPadding="false" </FrameLayout>
android:orientation="vertical"
android:padding="@dimen/element_spacing_small"
app:ignorePadding="true">
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.ColorLabelLinearLayout
android:id="@+id/name" android:id="@+id/profile_name_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:singleLine="true" android:layout_below="@+id/profile_banner_space"
android:text="@string/name" android:layout_toRightOf="@+id/profile_image_container"
android:textAppearance="?android:textAppearanceMedium"/> android:background="?android:selectableItemBackground"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small"
app:ignorePadding="true">
<LinearLayout <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent" android:id="@+id/name"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:orientation="horizontal"> android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/name"
android:textAppearance="?android:textAppearanceMedium"/>
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:id="@+id/screen_name" android:layout_width="match_parent"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:orientation="horizontal">
android:layout_weight="1"
android:singleLine="true"
android:text="@string/screen_name"
android:textAppearance="?android:textAppearanceSmall"/>
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/following_you_indicator" android:id="@+id/screen_name"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="0" android:layout_weight="1"
android:singleLine="true" android:singleLine="true"
android:text="@string/following_you" android:text="@string/screen_name"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceSmall"/>
android:textColor="?android:textColorTertiary"
android:visibility="gone"/>
</LinearLayout>
</org.mariotaku.twidere.view.ColorLabelLinearLayout>
<org.mariotaku.twidere.view.CardItemLinearLayout <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/card" android:id="@+id/following_you_indicator"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/profile_name_container" android:layout_weight="0"
android:orientation="vertical" android:singleLine="true"
android:padding="@dimen/element_spacing_normal" android:text="@string/following_you"
android:splitMotionEvents="false"> android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorTertiary"
android:visibility="gone"/>
</LinearLayout>
</org.mariotaku.twidere.view.ColorLabelLinearLayout>
<LinearLayout <org.mariotaku.twidere.view.CardItemLinearLayout
android:id="@+id/description_container" android:id="@+id/card"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:selectableItemBackground" android:layout_below="@+id/profile_name_container"
android:clickable="true" android:orientation="vertical"
android:orientation="vertical" android:padding="@dimen/element_spacing_normal"
android:padding="@dimen/element_spacing_small"> android:splitMotionEvents="false">
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:layout_width="match_parent" android:id="@+id/description_container"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:text="@string/description" android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceMedium"/> android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.HandleSpanClickTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/description" android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:text="@string/description"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceMedium"/>
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<LinearLayout <org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/location_container" android:id="@+id/description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:selectableItemBackground" android:textAppearance="?android:textAppearanceSmall"
android:clickable="true" android:textColor="?android:textColorSecondary"/>
android:orientation="vertical" </LinearLayout>
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:layout_width="match_parent" android:id="@+id/location_container"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:singleLine="true" android:layout_height="wrap_content"
android:text="@string/location" android:background="?android:selectableItemBackground"
android:textAppearance="?android:textAppearanceMedium"/> android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/location" android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:singleLine="true"
android:singleLine="true" android:text="@string/location"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceMedium"/>
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<LinearLayout <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/url_container" android:id="@+id/location"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:selectableItemBackground" android:singleLine="true"
android:clickable="true" android:textAppearance="?android:textAppearanceSmall"
android:orientation="vertical" android:textColor="?android:textColorSecondary"/>
android:padding="@dimen/element_spacing_small"> </LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:layout_width="match_parent" android:id="@+id/url_container"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:singleLine="true" android:layout_height="wrap_content"
android:text="@string/url" android:background="?android:selectableItemBackground"
android:textAppearance="?android:textAppearanceMedium"/> android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.HandleSpanClickTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/url" android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:singleLine="true"
android:autoLink="web" android:text="@string/url"
android:singleLine="true" android:textAppearance="?android:textAppearanceMedium"/>
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<LinearLayout <org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/created_at_container" android:id="@+id/url"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:selectableItemBackground" android:autoLink="web"
android:clickable="true" android:singleLine="true"
android:orientation="vertical" android:textAppearance="?android:textAppearanceSmall"
android:padding="@dimen/element_spacing_small"> android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:layout_width="wrap_content" android:id="@+id/created_at_container"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:singleLine="true" android:layout_height="wrap_content"
android:text="@string/created_at" android:background="?android:selectableItemBackground"
android:textAppearance="?android:textAppearanceMedium"/> android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/created_at" android:layout_width="wrap_content"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:singleLine="true"
android:singleLine="true" android:text="@string/created_at"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceMedium"/>
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<View <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent" android:id="@+id/created_at"
android:layout_height="0.2dp" android:layout_width="wrap_content"
android:background="@color/divider_color"/> android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<LinearLayout <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/action_button_size" android:layout_height="0.2dp"
android:baselineAligned="false" android:background="@color/divider_color"/>
android:divider="@drawable/divider_vertical_small_holo"
android:orientation="horizontal"
android:showDividers="middle"
android:splitMotionEvents="false">
<LinearLayout <LinearLayout
android:id="@+id/tweets_container" android:layout_width="match_parent"
android:layout_width="0dp" android:layout_height="@dimen/action_button_size"
android:layout_height="match_parent" android:baselineAligned="false"
android:layout_weight="1" android:divider="@drawable/divider_vertical_small_holo"
android:background="?android:selectableItemBackground" android:orientation="horizontal"
android:clickable="true" android:showDividers="middle"
android:gravity="center" android:splitMotionEvents="false">
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:id="@+id/statuses_count" android:id="@+id/tweets_container"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:singleLine="true" android:layout_weight="1"
android:textAppearance="?android:textAppearanceMedium" android:background="?android:selectableItemBackground"
android:textColor="?android:textColorPrimary"/> android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content" android:id="@+id/statuses_count"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:singleLine="true" android:layout_height="wrap_content"
android:text="@string/statuses" android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorPrimary"/>
</LinearLayout>
<LinearLayout <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/followers_container" android:layout_width="wrap_content"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_height="match_parent" android:singleLine="true"
android:layout_weight="1" android:text="@string/statuses"
android:background="?android:selectableItemBackground" android:textAppearance="?android:textAppearanceSmall"
android:clickable="true" android:textColor="?android:textColorSecondary"/>
android:gravity="center" </LinearLayout>
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:id="@+id/followers_count" android:id="@+id/followers_container"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:singleLine="true" android:layout_weight="1"
android:textAppearance="?android:textAppearanceMedium" android:background="?android:selectableItemBackground"
android:textColor="?android:textColorPrimary"/> android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content" android:id="@+id/followers_count"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:singleLine="true" android:layout_height="wrap_content"
android:text="@string/followers" android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorPrimary"/>
</LinearLayout>
<LinearLayout <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/friends_container" android:layout_width="wrap_content"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_height="match_parent" android:singleLine="true"
android:layout_weight="1" android:text="@string/followers"
android:background="?android:selectableItemBackground" android:textAppearance="?android:textAppearanceSmall"
android:clickable="true" android:textColor="?android:textColorSecondary"/>
android:gravity="center" </LinearLayout>
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <LinearLayout
android:id="@+id/friends_count" android:id="@+id/friends_container"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:singleLine="true" android:layout_weight="1"
android:textAppearance="?android:textAppearanceMedium" android:background="?android:selectableItemBackground"
android:textColor="?android:textColorPrimary"/> android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content" android:id="@+id/friends_count"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:singleLine="true" android:layout_height="wrap_content"
android:text="@string/following" android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorPrimary"/>
</LinearLayout>
</LinearLayout> <org.mariotaku.twidere.view.themed.ThemedTextView
</org.mariotaku.twidere.view.CardItemLinearLayout> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/following"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout>
</org.mariotaku.twidere.view.CardItemLinearLayout>
</RelativeLayout> </RelativeLayout>

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"
android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_gravity="top" android:layout_height="wrap_content"
android:scaleType="centerCrop"/> android:layout_gravity="top"
android:foreground="@drawable/shadow_bottom"
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,8 +1,9 @@
<?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:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"
android:key="settings_content" xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/content_and_storage"> android:key="settings_content"
android:title="@string/content_and_storage">
<PreferenceCategory <PreferenceCategory
android:key="category_multimedia_contents" android:key="category_multimedia_contents"
@ -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=""