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:cardview-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.sothree.slidinguppanel:library:2.0.0'
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();
mListView.setChoiceMode(isSingleSelection ? ListView.CHOICE_MODE_NONE : ListView.CHOICE_MODE_MULTIPLE);
mAdapter.setChoiceMode(mListView.getChoiceMode());
mAdapter.setSortEnabled(false);
if (isSingleSelection) {
mListView.setOnItemClickListener(this);
}

View File

@ -31,6 +31,8 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.graphics.Palette;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
@ -40,7 +42,6 @@ import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
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.provider.TweetStore.Accounts;
import org.mariotaku.twidere.task.AsyncTask;
import org.mariotaku.twidere.util.ColorAnalyser;
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator;
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticationException;
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.net.TwidereHostResolverFactory;
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.CroutonLifecycleCallback;
@ -98,15 +97,12 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
private int mAuthType;
private String mConsumerKey, mConsumerSecret;
private String mUsername, mPassword;
private Integer mUserColor;
private long mLoggedId;
private boolean mBackPressed;
private long mAPIChangeTimestamp;
private EditText mEditUsername, mEditPassword;
private Button mSignInButton, mSignUpButton;
private LinearLayout mSigninSignupContainer, mUsernamePasswordContainer;
private ImageButton mSetColorButton;
private TwidereApplication mApplication;
private SharedPreferences mPreferences;
@ -144,15 +140,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
invalidateOptionsMenu();
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: {
if (resultCode == BaseSupportActivity.RESULT_OK && data != null) {
doLogin(data);
@ -190,16 +177,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
doLogin();
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: {
new SignInMethodIntroductionDialogFragment().show(getSupportFragmentManager(),
"sign_in_method_introduction");
@ -217,7 +194,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mSignUpButton = (Button) findViewById(R.id.sign_up);
mSigninSignupContainer = (LinearLayout) findViewById(R.id.sign_in_sign_up);
mUsernamePasswordContainer = (LinearLayout) findViewById(R.id.username_password);
mSetColorButton = (ImageButton) findViewById(R.id.set_color);
}
@Override
@ -309,9 +285,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
outState.putString(Accounts.SCREEN_NAME, mUsername);
outState.putString(Accounts.PASSWORD, mPassword);
outState.putLong(EXTRA_API_LAST_CHANGE, mAPIChangeTimestamp);
if (mUserColor != null) {
outState.putInt(Accounts.COLOR, mUserColor);
}
super.onSaveInstanceState(outState);
}
@ -340,9 +313,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mConsumerSecret = trim(savedInstanceState.getString(Accounts.CONSUMER_SECRET));
mUsername = savedInstanceState.getString(Accounts.SCREEN_NAME);
mPassword = savedInstanceState.getString(Accounts.PASSWORD);
if (savedInstanceState.containsKey(Accounts.COLOR)) {
mUserColor = savedInstanceState.getInt(Accounts.COLOR, Color.TRANSPARENT);
}
mAPIChangeTimestamp = savedInstanceState.getLong(EXTRA_API_LAST_CHANGE);
}
@ -356,7 +326,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mEditPassword.setText(mPassword);
mEditPassword.addTextChangedListener(this);
setSignInButton();
setUserColorButton();
}
private void doLogin() {
@ -366,7 +335,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
saveEditedText();
setDefaultAPI();
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);
mTask.execute();
}
@ -382,7 +351,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
final String token = intent.getStringExtra(EXTRA_REQUEST_TOKEN);
final String secret = intent.getStringExtra(EXTRA_REQUEST_TOKEN_SECRET);
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);
mTask.execute();
}
@ -472,14 +441,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
|| 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) {
if (result != null) {
if (result.succeed) {
@ -510,10 +471,10 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
if (values != null) {
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 Bundle bundle = new Bundle();
bundle.putLongArray(EXTRA_IDS, new long[]{mLoggedId});
bundle.putLongArray(EXTRA_IDS, new long[]{loggedId});
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
@ -537,7 +498,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mEditUsername.setEnabled(true);
mSignInButton.setEnabled(true);
mSignUpButton.setEnabled(true);
mSetColorButton.setEnabled(true);
setSignInButton();
}
@ -547,7 +507,6 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
mEditUsername.setEnabled(false);
mSignInButton.setEnabled(false);
mSignUpButton.setEnabled(false);
mSetColorButton.setEnabled(false);
}
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 {
if (user == null) throw new TwitterException("Unable to get user info");
final HttpClientWrapper client = new HttpClientWrapper(conf);
final String profileImageUrl = ParseUtils.parseString(user.getProfileImageURL());
final HttpResponse conn = profileImageUrl != null ? client.get(profileImageUrl, null) : null;
final Bitmap bm = conn != null ? BitmapFactory.decodeStream(conn.asStream()) : null;
if (bm == null) {
try {
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");
}
}
final int profileBackgroundColor = getProfileBackgroundColor(user.getProfileBackgroundColor());
if (bm == null) return profileBackgroundColor;
try {
return ColorAnalyser.analyse(bm);
return Palette.generate(bm).getVibrantColor(profileBackgroundColor);
} finally {
bm.recycle();
}
@ -603,22 +563,21 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
private final Configuration conf;
private final String request_token, request_token_secret, oauth_verifier;
private final Integer user_color;
private final Context context;
private final String api_url_format;
private final boolean same_oauth_signing_url, no_version_suffix;
public BrowserSignInTask(final SignInActivity context, final Configuration conf, final String request_token,
final String request_token_secret, final String oauth_verifier, final Integer user_color,
final String api_url_format, final boolean same_oauth_signing_url, final boolean no_version_suffix) {
public BrowserSignInTask(final SignInActivity context, final Configuration conf,
final String request_token, final String request_token_secret,
final String oauth_verifier, final String api_url_format,
final boolean same_oauth_signing_url, final boolean no_version_suffix) {
super(context, conf);
this.context = context;
this.conf = conf;
this.request_token = request_token;
this.request_token_secret = request_token_secret;
this.oauth_verifier = oauth_verifier;
this.user_color = user_color;
this.api_url_format = api_url_format;
this.same_oauth_signing_url = same_oauth_signing_url;
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);
final User user = twitter.verifyCredentials();
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,
api_url_format, same_oauth_signing_url, no_version_suffix);
} catch (final TwitterException e) {
@ -645,6 +604,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
public static class SignInMethodIntroductionDialogFragment extends BaseSupportDialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
@ -662,22 +622,21 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
private final Configuration conf;
private final String username, password;
private final int auth_type;
private final Integer user_color;
private final Context context;
private final String api_url_format;
private final boolean same_oauth_signing_url, no_version_suffix;
public SignInTask(final SignInActivity context, final Configuration conf, final String username,
final String password, final int auth_type, final Integer user_color, final String api_url_format,
final boolean same_oauth_signing_url, final boolean no_version_suffix) {
public SignInTask(final SignInActivity context, final Configuration conf,
final String username, final String password, final int auth_type,
final String api_url_format, final boolean same_oauth_signing_url,
final boolean no_version_suffix) {
super(context, conf);
this.context = context;
this.conf = conf;
this.username = username;
this.password = password;
this.auth_type = auth_type;
this.user_color = user_color;
this.api_url_format = api_url_format;
this.same_oauth_signing_url = same_oauth_signing_url;
this.no_version_suffix = no_version_suffix;
@ -712,7 +671,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
final long user_id = user.getId();
if (user_id <= 0) return new SignInResponse(false, 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,
no_version_suffix);
}
@ -725,7 +684,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
if (user_id <= 0) return new SignInResponse(false, false, null);
final User user = twitter.verifyCredentials();
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,
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();
if (user_id <= 0) return new SignInResponse(false, 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);
}
@ -747,7 +706,7 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
final long user_id = user.getId();
if (user_id <= 0) return new SignInResponse(false, 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,
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);
}
static interface SigninCallback {
void onSigninResult(SignInResponse response);
void onSigninStart();
}
static class SignInResponse {
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.adapter.iface.IBaseAdapter;
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.util.ImageLoaderWrapper;
import org.mariotaku.twidere.view.holder.AccountViewHolder;
@ -41,11 +43,12 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
private final ImageLoaderWrapper mImageLoader;
private final SharedPreferences mPreferences;
private int mUserColorIdx, mProfileImageIdx, mScreenNameIdx, mAccountIdIdx;
private long mDefaultAccountId;
private boolean mDisplayProfileImage;
private int mChoiceMode;
private boolean mSortEnabled;
private Indices mIndices;
public AccountsAdapter(final Context context) {
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);
}
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
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();
holder.screen_name.setText("@" + cursor.getString(mScreenNameIdx));
holder.screen_name.setText("@" + cursor.getString(mIndices.screen_name));
holder.setAccountColor(color);
holder.setIsDefault(mDefaultAccountId != -1 && mDefaultAccountId == cursor.getLong(mAccountIdIdx));
holder.setIsDefault(mDefaultAccountId != -1 && mDefaultAccountId == cursor.getLong(mIndices.account_id));
if (mDisplayProfileImage) {
mImageLoader.displayProfileImage(holder.profile_image, cursor.getString(mProfileImageIdx));
mImageLoader.displayProfileImage(holder.profile_image, cursor.getString(mIndices.profile_image_url));
} else {
mImageLoader.cancelDisplayTask(holder.profile_image);
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
|| mChoiceMode == ListView.CHOICE_MODE_MULTIPLE_MODAL;
holder.checkbox.setVisibility(isMultipleChoice ? View.VISIBLE : View.GONE);
holder.setSortEnabled(mSortEnabled);
super.bindView(view, context, cursor);
}
@ -173,11 +183,14 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
@Override
public Cursor swapCursor(final Cursor cursor) {
if (cursor != null) {
mAccountIdIdx = cursor.getColumnIndex(Accounts.ACCOUNT_ID);
mUserColorIdx = cursor.getColumnIndex(Accounts.COLOR);
mProfileImageIdx = cursor.getColumnIndex(Accounts.PROFILE_IMAGE_URL);
mScreenNameIdx = cursor.getColumnIndex(Accounts.SCREEN_NAME);
mIndices = new Indices(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;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
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.iface.IThemedActivity;
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.HomeActivity;
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.model.Account;
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.ThemeUtils;
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.openUserTimeline;
public class AccountsDrawerFragment extends BaseSupportListFragment implements LoaderCallbacks<Cursor>,
public class AccountsDashboardFragment extends BaseSupportListFragment implements LoaderCallbacks<Cursor>,
OnSharedPreferenceChangeListener, OnAccountActivateStateChangeListener {
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
this, 0, this);
private static final String FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion";
private ContentResolver mResolver;
private SharedPreferences mPreferences;
private MergeAdapter mAdapter;
@ -106,10 +94,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
private Context mThemedContext;
public Account getSelectedAccount() {
return mAccountsAdapter.getSelectedAccount();
}
@Override
public void onAccountActivateStateChanged(final Account account, final boolean activated) {
final ContentValues values = new ContentValues();
@ -151,16 +135,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
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: {
if (data == null) return;
final FragmentActivity activity = getActivity();
@ -243,25 +217,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
closeAccountsDrawer();
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) {
if (!(item instanceof OptionItem)) return;
@ -370,7 +325,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
private void updateDefaultAccountState() {
final long defaultAccountId = mAccountsAdapter.getDefaultAccountId();
final long selectedAccountId = mAccountsAdapter.getSelectedAccountId();
mAccountOptionsAdapter.setDefault(defaultAccountId == selectedAccountId);
}
private static TextView newSectionView(final Context context, final int titleRes) {
@ -381,47 +335,10 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
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 ArrayList<OptionItem> sOptions = new ArrayList<>();
private static final ArrayList<OptionItem> sOptionsDefault = new ArrayList<>();
static {
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.lists_following_me, R.drawable.ic_action_list,
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) {
@ -455,10 +356,6 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L
addAll(sOptions);
}
public void setDefault(final boolean isDefault) {
clear();
addAll(isDefault ? sOptionsDefault : sOptions);
}
}
private static final class AppMenuAdapter extends OptionItemsAdapter {

View File

@ -1,15 +1,27 @@
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.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -17,6 +29,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
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.twidere.R;
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
import org.mariotaku.twidere.activity.support.SignInActivity;
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.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 java.util.ArrayList;
@ -34,9 +55,13 @@ import java.util.ArrayList;
/**
* 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 SharedPreferences mPreferences;
private Account mSelectedAccount;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
@ -51,22 +76,136 @@ public class AccountsManagerFragment extends BaseSupportListFragment implements
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
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
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
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
final FragmentActivity activity = getActivity();
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mPreferences.registerOnSharedPreferenceChangeListener(this);
mAdapter = new AccountsAdapter(activity);
Utils.configBaseAdapter(activity, mAdapter);
setListAdapter(mAdapter);
final DragSortListView listView = (DragSortListView) getListView();
listView.setDragEnabled(true);
listView.setDropListener(this);
listView.setOnCreateContextMenuListener(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.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@ -60,7 +61,6 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
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.FlymeUtils;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.MathUtils;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.ThemeUtils;
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.view.ColorLabelLinearLayout;
import org.mariotaku.twidere.view.ExtendedFrameLayout;
import org.mariotaku.twidere.view.ProfileBannerImageView;
import org.mariotaku.twidere.view.ProfileImageView;
import org.mariotaku.twidere.view.TwidereMenuBar;
import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener;
@ -152,7 +154,7 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
private SharedPreferences mPreferences;
private ProfileImageView mProfileImageView;
private ImageView mProfileBannerView;
private ProfileBannerImageView mProfileBannerView;
private TextView mNameView, mScreenNameView, mDescriptionView, mLocationView, mURLView, mCreatedAtView,
mTweetCount, mFollowersCount, mFriendsCount, mErrorMessageView;
private View mDescriptionContainer, mLocationContainer, mURLContainer, mTweetsContainer, mFollowersContainer,
@ -164,9 +166,9 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
private View mErrorRetryContainer;
private View mFollowingYouIndicator;
private View mMainContent;
private View mProfileBannerSpace;
private ProgressBar mDetailsLoadProgress;
private TwidereMenuBar mMenuBar;
private View mProfileBannerSpace;
private ListActionAdapter mAdapter;
@ -385,7 +387,9 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
final String where = Accounts.ACCOUNT_ID + " = " + user.id;
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 UserMentionsAction(3));
mAdapter.add(new UserListsAction(4));
@ -464,8 +468,9 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
mFollowersContainer.setOnClickListener(this);
mFriendsContainer.setOnClickListener(this);
mRetryButton.setOnClickListener(this);
mProfileBannerView.setOnSizeChangedListener(this);
mProfileBannerSpace.setOnTouchListener(this);
setListAdapter(null);
mListView = getListView();
mListView.addHeaderView(mHeaderView, null, false);
if (isUucky(userId, screenName, args.getParcelable(EXTRA_USER))) {
final View uuckyFooter = View.inflate(activity,
@ -480,8 +485,6 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
mMenuBar.setIsBottomBar(true);
mMenuBar.setOnMenuItemClickListener(this);
mProfileBannerSpace.setOnTouchListener(this);
setListAdapter(mAdapter);
getUserInfo(accountId, userId, screenName, false);
@ -498,13 +501,17 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
final int themeResId = linkHandler.getCurrentThemeResourceId();
final boolean isTransparent = ThemeUtils.isTransparentBackground(themeResId);
final int actionBarAlpha = isTransparent ? ThemeUtils.getUserThemeBackgroundAlpha(linkHandler) : 0xFF;
if (ThemeUtils.isColoredActionBar(themeResId)) {
if (ThemeUtils.isColoredActionBar(themeResId) && useUserActionBar()) {
actionBar.setBackgroundDrawable(mActionBarBackground = new ColorDrawable(themeColor));
} else {
actionBar.setBackgroundDrawable(mActionBarBackground = ThemeUtils.getActionBarBackground(activity, themeResId));
}
}
private boolean useUserActionBar() {
return false;
}
private boolean isUucky(long userId, String screenName, Parcelable parcelable) {
if (userId == UUCKY_ID || UUCKY_SCREEN_NAME.equalsIgnoreCase(screenName)) return true;
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);
break;
}
case R.id.profile_banner:
case R.id.profile_banner_space: {
case R.id.profile_banner: {
final String profile_banner_url = mUser.profile_banner_url;
if (profile_banner_url == null) return;
openImage(getActivity(), user.account_id, profile_banner_url + "/ipad_retina", false);
break;
}
case R.id.tweets_container: {
if (mUser == null) return;
openUserTimeline(getActivity(), user.account_id, user.id, user.screen_name);
break;
}
case R.id.followers_container: {
if (mUser == null) return;
openUserFollowers(getActivity(), user.account_id, user.id, user.screen_name);
break;
}
case R.id.friends_container: {
if (mUser == null) return;
openUserFriends(getActivity(), user.account_id, user.id, user.screen_name);
break;
}
@ -635,8 +638,7 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
@Override
public boolean onItemLongClick(final AdapterView<?> adapter, final View view, final int position, final long id) {
final ListAction action = mAdapter.findItem(id);
if (action != null) return action.onLongClick();
return false;
return action != null && action.onLongClick();
}
@Override
@ -710,14 +712,19 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
final int totalItemCount) {
super.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
final View headerView = mHeaderView, profileBannerView = mProfileBannerView;
if (headerView == null || profileBannerView == null) return;
final View headerView = mHeaderView;
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 int headerScroll = listView.getListPaddingTop() - headerView.getTop();
profileBannerView.setAlpha(1.0f - factor);
profileBannerView.setTranslationY(headerView.getTop() / 2);
profileBannerView.setTranslationY((headerView.getTop() - listView.getListPaddingTop()) / 2);
profileBannerView.setBottomClip(headerScroll);
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
public void onSizeChanged(final View view, final int w, final int h, final int oldw, final int oldh) {
mBannerWidth = w;
if (w != oldw || h != oldh) {
requestFitSystemWindows();
}
}
@Override
@ -754,17 +764,26 @@ public class UserProfileFragmentOld extends BaseSupportListFragment implements O
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
public void onViewCreated(final View view, final Bundle savedInstanceState) {
final Context context = view.getContext();
super.onViewCreated(view, savedInstanceState);
mMainContent = view.findViewById(R.id.content);
mListView = (ListView) view.findViewById(android.R.id.list);
mDetailsLoadProgress = (ProgressBar) view.findViewById(R.id.details_load_progress);
mMenuBar = (TwidereMenuBar) view.findViewById(R.id.menu_bar);
mErrorRetryContainer = view.findViewById(R.id.error_retry_container);
mRetryButton = (Button) view.findViewById(R.id.retry);
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);
mScreenNameView = (TextView) mHeaderView.findViewById(R.id.screen_name);
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_banner_url = indices.profile_banner_url != -1 ? cursor.getString(indices.profile_banner_url) : null;
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) {

View File

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

View File

@ -21,15 +21,19 @@ package org.mariotaku.twidere.preference;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
@ -52,180 +56,175 @@ import java.util.List;
public abstract class AccountsListPreference extends PreferenceCategory implements Constants {
private static final int[] ATTRS = { R.attr.switchKey, R.attr.switchDefault };
private final String mSwitchKey;
private final boolean mSwitchDefault;
private static final int[] ATTRS = {R.attr.switchKey, R.attr.switchDefault};
private final String mSwitchKey;
private final boolean mSwitchDefault;
public AccountsListPreference(final Context context) {
this(context, null);
}
public AccountsListPreference(final Context context) {
this(context, null);
}
public AccountsListPreference(final Context context, final AttributeSet attrs) {
this(context, attrs, android.R.attr.preferenceCategoryStyle);
}
public AccountsListPreference(final Context context, final AttributeSet attrs) {
this(context, attrs, android.R.attr.preferenceCategoryStyle);
}
public AccountsListPreference(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
mSwitchKey = a.getString(0);
mSwitchDefault = a.getBoolean(1, false);
a.recycle();
}
public AccountsListPreference(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
mSwitchKey = a.getString(0);
mSwitchDefault = a.getBoolean(1, false);
a.recycle();
}
public void setAccountsData(final List<Account> accounts) {
removeAll();
for (final Account account : accounts) {
final AccountItemPreference preference = new AccountItemPreference(getContext(), account, mSwitchKey,
mSwitchDefault);
setupPreference(preference, account);
addPreference(preference);
}
final Preference preference = new Preference(getContext());
preference.setLayoutResource(R.layout.settings_layout_click_to_config);
addPreference(preference);
}
public void setAccountsData(final List<Account> accounts) {
removeAll();
for (final Account account : accounts) {
final AccountItemPreference preference = new AccountItemPreference(getContext(), account, mSwitchKey,
mSwitchDefault);
setupPreference(preference, account);
addPreference(preference);
}
final Preference preference = new Preference(getContext());
preference.setLayoutResource(R.layout.settings_layout_click_to_config);
addPreference(preference);
}
@Override
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) {
super.onAttachedToHierarchy(preferenceManager);
new LoadAccountsTask(this).execute();
}
@Override
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) {
super.onAttachedToHierarchy(preferenceManager);
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,
OnCheckedChangeListener, OnSharedPreferenceChangeListener {
public static final class AccountItemPreference extends Preference implements ImageLoadingListener,
OnCheckedChangeListener, OnSharedPreferenceChangeListener, OnPreferenceClickListener, OnClickListener {
private final Account mAccount;
private final SharedPreferences mSwitchPreference;
private final String mSwitchKey;
private final boolean mSwitchDefault;
private final float mDensity;
private final Account mAccount;
private final SharedPreferences mSwitchPreference;
private final String mSwitchKey;
private final boolean mSwitchDefault;
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,
final boolean switchDefault) {
super(context);
final String switchPreferenceName = ACCOUNT_PREFERENCES_NAME_PREFIX + account.account_id;
mAccount = account;
mDensity = context.getResources().getDisplayMetrics().density;
mSwitchPreference = context.getSharedPreferences(switchPreferenceName, Context.MODE_PRIVATE);
mSwitchKey = switchKey;
mSwitchDefault = switchDefault;
mSwitchPreference.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
if (mSwitchKey == null) return;
final SharedPreferences.Editor editor = mSwitchPreference.edit();
editor.putBoolean(mSwitchKey, isChecked);
editor.apply();
}
@Override
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
if (mSwitchKey == null) return;
final SharedPreferences.Editor editor = mSwitchPreference.edit();
editor.putBoolean(mSwitchKey, isChecked);
editor.apply();
}
@Override
public void onLoadingCancelled(final String imageUri, final View view) {
setIcon(R.drawable.ic_profile_image_default);
}
@Override
public void onLoadingCancelled(final String imageUri, final View view) {
setIcon(R.drawable.ic_profile_image_default);
}
@Override
public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) {
setIcon(new BitmapDrawable(getContext().getResources(), loadedImage));
}
@Override
public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) {
setIcon(new BitmapDrawable(getContext().getResources(), loadedImage));
}
@Override
public void onLoadingFailed(final String imageUri, final View view, final FailReason failReason) {
setIcon(R.drawable.ic_profile_image_default);
}
@Override
public void onLoadingFailed(final String imageUri, final View view, final FailReason failReason) {
setIcon(R.drawable.ic_profile_image_default);
}
@Override
public void onLoadingStarted(final String imageUri, final View view) {
setIcon(R.drawable.ic_profile_image_default);
}
@Override
public void onLoadingStarted(final String imageUri, final View view) {
setIcon(R.drawable.ic_profile_image_default);
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
notifyChanged();
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
updateSwitchState();
}
@Override
protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) {
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
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) {
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
protected View onCreateView(ViewGroup parent) {
final View view = super.onCreateView(parent);
view.findViewById(R.id.settings).setOnClickListener(this);
final Switch toggle = (Switch) view.findViewById(android.R.id.toggle);
toggle.setOnCheckedChangeListener(this);
return view;
}
@Override
protected void onBindView(final View view) {
super.onBindView(view);
mView = view;
final View iconView = view.findViewById(android.R.id.icon);
if (iconView instanceof ImageView) {
((ImageView) iconView).setScaleType(ScaleType.FIT_CENTER);
}
final View titleView = view.findViewById(android.R.id.title);
if (titleView instanceof TextView) {
((TextView) titleView).setSingleLine(true);
}
final View summaryView = view.findViewById(android.R.id.summary);
if (summaryView instanceof TextView) {
((TextView) summaryView).setSingleLine(true);
}
updateSwitchState();
}
@Override
protected void onBindView(@NonNull final View view) {
super.onBindView(view);
final View iconView = view.findViewById(android.R.id.icon);
if (iconView instanceof ImageView) {
((ImageView) iconView).setScaleType(ScaleType.FIT_CENTER);
}
final View titleView = view.findViewById(android.R.id.title);
if (titleView instanceof TextView) {
((TextView) titleView).setSingleLine(true);
}
final View summaryView = view.findViewById(android.R.id.summary);
if (summaryView instanceof TextView) {
((TextView) summaryView).setSingleLine(true);
}
final Switch toggle = (Switch) view.findViewById(android.R.id.toggle);
if (mSwitchKey != null) {
toggle.setChecked(mSwitchPreference.getBoolean(mSwitchKey, mSwitchDefault));
}
}
private void updateSwitchState() {
if (mView == null) return;
final View widgetFrameView = mView.findViewById(android.R.id.widget_frame);
if (!(widgetFrameView instanceof ViewGroup)) return;
final ViewGroup widgetFrame = (ViewGroup) widgetFrameView;
widgetFrame.setVisibility(mSwitchKey != null ? View.VISIBLE : View.GONE);
widgetFrame.setPadding(widgetFrame.getPaddingLeft(), widgetFrame.getPaddingTop(), (int) (mDensity * 8),
widgetFrame.getPaddingBottom());
widgetFrame.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
// remove preview image that is already created
widgetFrame.setAlpha(isEnabled() ? 1 : 0.25f);
final View foundView = widgetFrame.findViewById(android.R.id.toggle);
final Switch toggle;
if (foundView instanceof Switch) {
toggle = (Switch) foundView;
} else {
widgetFrame.removeAllViews();
toggle = new Switch(getContext());
toggle.setId(android.R.id.toggle);
toggle.setOnCheckedChangeListener(this);
widgetFrame.addView(toggle);
}
if (mSwitchKey != null) {
toggle.setChecked(mSwitchPreference.getBoolean(mSwitchKey, mSwitchDefault));
}
}
@Override
public boolean onPreferenceClick(Preference preference) {
}
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) {
mPreference = preference;
}
private final AccountsListPreference mPreference;
@Override
protected List<Account> doInBackground(final Void... params) {
return Account.getAccountsList(mPreference.getContext(), false);
}
public LoadAccountsTask(final AccountsListPreference preference) {
mPreference = preference;
}
@Override
protected void onPostExecute(final List<Account> result) {
mPreference.setAccountsData(result);
}
@Override
protected List<Account> doInBackground(final Void... params) {
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
* integer from a {@link SeekBar}, and persist it.
*
*
* @author lukehorvat
*/
public class SeekBarDialogPreference extends DialogPreference {
private static final int DEFAULT_MIN_PROGRESS = 0;
private static final int DEFAULT_MAX_PROGRESS = 100;
private static final int DEFAULT_PROGRESS = 0;
private static final int DEFAULT_MIN_PROGRESS = 0;
private static final int DEFAULT_MAX_PROGRESS = 100;
private static final int DEFAULT_PROGRESS = 0;
private static final int DEFAULT_STEP = 1;
private int mMinProgress;
private int mMaxProgress;
private int mProgress;
private CharSequence mProgressTextSuffix;
private TextView mProgressText;
private SeekBar mSeekBar;
private int mMinProgress;
private int mMaxProgress;
private int mProgress;
private int mStep;
public SeekBarDialogPreference(final Context context) {
this(context, null);
}
private CharSequence mProgressTextSuffix;
private TextView mProgressText;
private SeekBar mSeekBar;
public SeekBarDialogPreference(final Context context, final AttributeSet attrs) {
this(context, attrs, android.R.attr.dialogPreferenceStyle);
}
public SeekBarDialogPreference(final Context context) {
this(context, null);
}
public SeekBarDialogPreference(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
public SeekBarDialogPreference(final Context context, final AttributeSet attrs) {
this(context, attrs, android.R.attr.dialogPreferenceStyle);
}
// get attributes specified in XML
final TypedArray a = context.getTheme()
.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();
}
public SeekBarDialogPreference(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
// set layout
setDialogLayoutResource(R.layout.preference_seek_bar_dialog);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
setDialogIcon(null);
}
// get attributes specified in XML
final TypedArray a = context.getTheme()
.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));
setStep(a.getInteger(R.styleable.SeekBarDialogPreference_step, DEFAULT_STEP));
setProgressTextSuffix(a.getString(R.styleable.SeekBarDialogPreference_progressTextSuffix));
} finally {
a.recycle();
}
public int getMaxProgress() {
return mMaxProgress;
}
// set layout
setDialogLayoutResource(R.layout.preference_seek_bar_dialog);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
setDialogIcon(null);
}
public int getMinProgress() {
return mMinProgress;
}
public void setStep(int step) {
mStep = step;
}
public int getProgress() {
return mProgress;
}
public int getMaxProgress() {
return mMaxProgress;
}
public CharSequence getProgressTextSuffix() {
return mProgressTextSuffix;
}
public int getMinProgress() {
return mMinProgress;
}
public void setMaxProgress(final int maxProgress) {
mMaxProgress = maxProgress;
setProgress(Math.min(mProgress, mMaxProgress));
}
public int getProgress() {
return mProgress;
}
public void setMinProgress(final int minProgress) {
mMinProgress = minProgress;
setProgress(Math.max(mProgress, mMinProgress));
}
public CharSequence getProgressTextSuffix() {
return mProgressTextSuffix;
}
public void setProgress(int progress) {
progress = Math.max(Math.min(progress, mMaxProgress), mMinProgress);
public void setMaxProgress(final int maxProgress) {
mMaxProgress = maxProgress;
setProgress(Math.min(mProgress, mMaxProgress));
}
if (progress != mProgress) {
mProgress = progress;
persistInt(progress);
notifyChanged();
}
}
public void setMinProgress(final int minProgress) {
mMinProgress = minProgress;
setProgress(Math.max(mProgress, mMinProgress));
}
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
protected void onBindDialogView(final View view) {
super.onBindDialogView(view);
if (progress != mProgress) {
mProgress = progress;
persistInt(progress);
notifyChanged();
}
}
final CharSequence message = getDialogMessage();
final TextView dialogMessageText = (TextView) view.findViewById(R.id.text_dialog_message);
dialogMessageText.setText(message);
dialogMessageText.setVisibility(TextUtils.isEmpty(message) ? View.GONE : View.VISIBLE);
public void setProgressTextSuffix(final CharSequence progressTextSuffix) {
mProgressTextSuffix = progressTextSuffix;
}
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);
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
// 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()));
}
final CharSequence message = getDialogMessage();
final TextView dialogMessageText = (TextView) view.findViewById(R.id.text_dialog_message);
dialogMessageText.setText(message);
dialogMessageText.setVisibility(TextUtils.isEmpty(message) ? View.GONE : View.VISIBLE);
@Override
public void onStartTrackingTouch(final SeekBar seekBar) {
}
mProgressText = (TextView) view.findViewById(R.id.text_progress);
@Override
public void onStopTrackingTouch(final SeekBar seekBar) {
}
});
mSeekBar.setMax(mMaxProgress - mMinProgress);
mSeekBar.setProgress(mProgress - mMinProgress);
}
mSeekBar = (SeekBar) view.findViewById(R.id.seek_bar);
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
// 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 * mStep + mMinProgress);
mProgressText.setText(mProgressTextSuffix == null ? progressStr : progressStr
.concat(mProgressTextSuffix.toString()));
}
@Override
protected void onDialogClosed(final boolean positiveResult) {
super.onDialogClosed(positiveResult);
@Override
public void onStartTrackingTouch(final SeekBar seekBar) {
}
// when the user selects "OK", persist the new value
if (positiveResult) {
final int seekBarProgress = mSeekBar.getProgress() + mMinProgress;
if (callChangeListener(seekBarProgress)) {
setProgress(seekBarProgress);
}
}
}
@Override
public void onStopTrackingTouch(final SeekBar seekBar) {
}
});
mSeekBar.setMax((int) Math.ceil((mMaxProgress - mMinProgress) / (double) mStep));
mSeekBar.setProgress((int) Math.ceil((mProgress - mMinProgress) / (double) mStep));
}
@Override
protected Object onGetDefaultValue(final TypedArray a, final int index) {
return a.getInt(index, DEFAULT_PROGRESS);
}
@Override
protected void onDialogClosed(final boolean positiveResult) {
super.onDialogClosed(positiveResult);
@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;
}
// when the user selects "OK", persist the new value
if (positiveResult) {
final int realProgress = mSeekBar.getProgress() * mStep + mMinProgress;
if (callChangeListener(realProgress)) {
setProgress(realProgress);
}
}
}
// restore the state
final SavedState myState = (SavedState) state;
setMinProgress(myState.minProgress);
setMaxProgress(myState.maxProgress);
setProgress(myState.progress);
@Override
protected Object onGetDefaultValue(final TypedArray a, final int index) {
return a.getInt(index, DEFAULT_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
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();
// restore the state
final SavedState myState = (SavedState) state;
setMinProgress(myState.minProgress);
setMaxProgress(myState.maxProgress);
setProgress(myState.progress);
setStep(myState.step);
// set the state's value with the class member that holds current
// setting value
final SavedState myState = new SavedState(superState);
myState.minProgress = getMinProgress();
myState.maxProgress = getMaxProgress();
myState.progress = getProgress();
super.onRestoreInstanceState(myState.getSuperState());
}
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
protected void onSetInitialValue(final boolean restore, final Object defaultValue) {
setProgress(restore ? getPersistedInt(DEFAULT_PROGRESS) : (Integer) defaultValue);
}
// set the state's value with the class member that holds current
// setting value
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 {
int minProgress;
int maxProgress;
int progress;
private int getStep() {
return mStep;
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(final Parcel in) {
return new SavedState(in);
}
@Override
protected void onSetInitialValue(final boolean restore, final Object defaultValue) {
setProgress(restore ? getPersistedInt(DEFAULT_PROGRESS) : (Integer) defaultValue);
}
@Override
public SavedState[] newArray(final int size) {
return new SavedState[size];
}
};
private static class SavedState extends BaseSavedState {
int minProgress;
int maxProgress;
int progress;
int step;
public SavedState(final Parcel source) {
super(source);
@SuppressWarnings("unused")
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();
maxProgress = source.readInt();
progress = source.readInt();
}
@Override
public SavedState[] newArray(final int size) {
return new SavedState[size];
}
};
public SavedState(final Parcelable superState) {
super(superState);
}
public SavedState(final Parcel source) {
super(source);
@Override
public void writeToParcel(final Parcel dest, final int flags) {
super.writeToParcel(dest, flags);
minProgress = source.readInt();
maxProgress = source.readInt();
progress = source.readInt();
step = source.readInt();
}
dest.writeInt(minProgress);
dest.writeInt(maxProgress);
dest.writeInt(progress);
}
}
public SavedState(final Parcelable superState) {
super(superState);
}
@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
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
setValue(restorePersistedValue ? getPersistedString(mValue) : (String) defaultValue);
updateSummary();
}
private void updateSummary() {
@ -90,7 +91,6 @@ public class ThemeBackgroundPreference extends DialogPreference implements Const
private void setValue(String value) {
mValue = value;
updateSummary();
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.ImageLoader;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.mariotaku.twidere.Constants;
@ -55,6 +56,7 @@ public class ImageLoaderWrapper implements Constants {
bannerOptsBuilder.cacheInMemory(true);
bannerOptsBuilder.cacheOnDisk(true);
bannerOptsBuilder.bitmapConfig(Bitmap.Config.RGB_565);
bannerOptsBuilder.displayer(new FadeInBitmapDisplayer(200, true, true, false));
mProfileImageDisplayOptions = profileOptsBuilder.build();
mImageDisplayOptions = imageOptsBuilder.build();

View File

@ -2780,6 +2780,20 @@ public final class Utils implements Constants, TwitterConstants {
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) {
if (context == null || twitter == null) return false;
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;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.ImageView;
@ -29,86 +31,91 @@ import org.mariotaku.twidere.view.iface.IForegroundView;
public class ForegroundImageView extends ImageView implements IForegroundView {
private final ForegroundViewHelper mForegroundViewHelper;
private final ForegroundViewHelper mForegroundViewHelper;
public ForegroundImageView(final Context context) {
this(context, null);
}
public ForegroundImageView(final Context context) {
this(context, null);
}
public ForegroundImageView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ForegroundImageView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ForegroundImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
mForegroundViewHelper = new ForegroundViewHelper(this, context, attrs, defStyle);
}
public ForegroundImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
mForegroundViewHelper = new ForegroundViewHelper(this, context, attrs, defStyle);
}
@Override
public Drawable getForeground() {
return mForegroundViewHelper.getForeground();
}
@Override
public Drawable getForeground() {
return mForegroundViewHelper.getForeground();
}
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
mForegroundViewHelper.jumpDrawablesToCurrentState();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void drawableHotspotChanged(float x, float y) {
super.drawableHotspotChanged(x, y);
mForegroundViewHelper.dispatchDrawableHotspotChanged(x, y);
}
/**
* 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
* account by ensuring that the children are inset to be placed inside of
* 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);
}
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
mForegroundViewHelper.jumpDrawablesToCurrentState();
}
/**
* Describes how the foreground is positioned. Defaults to START and TOP.
*
* @param foregroundGravity See {@link android.view.Gravity}
*
* @attr ref android.R.styleable#FrameLayout_foregroundGravity
*/
@Override
public void setForegroundGravity(final int foregroundGravity) {
mForegroundViewHelper.setForegroundGravity(foregroundGravity);
}
/**
* 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
* account by ensuring that the children are inset to be placed inside of
* 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);
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
mForegroundViewHelper.drawableStateChanged();
}
/**
* Describes how the foreground is positioned. Defaults to START and TOP.
*
* @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
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
mForegroundViewHelper.dispatchOnDraw(canvas);
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
mForegroundViewHelper.drawableStateChanged();
}
@Override
protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) {
mForegroundViewHelper.dispatchOnLayout(changed, left, top, right, bottom);
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
mForegroundViewHelper.dispatchOnDraw(canvas);
}
@Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mForegroundViewHelper.dispatchOnSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) {
mForegroundViewHelper.dispatchOnLayout(changed, left, top, right, bottom);
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected boolean verifyDrawable(final Drawable who) {
return super.verifyDrawable(who) || mForegroundViewHelper.verifyDrawable(who);
}
@Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
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;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
@ -37,91 +35,87 @@ import org.mariotaku.twidere.view.iface.IExtendedView;
public class ProfileBannerImageView extends ForegroundImageView implements IExtendedView, Constants {
private static final int[] COLORS = new int[] { 0xFFFFFFFF, 0x00FFFFFF };
private static final int[] COLORS_REVERSED = new int[] { 0x00FFFFFF, 0xFFFFFFFF };
private static final float[] POSITIONS = new float[] { 0.0f, 1.0f };
private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
private OnSizeChangedListener mOnSizeChangedListener;
private TouchInterceptor mTouchInterceptor;
private OnSizeChangedListener mOnSizeChangedListener;
private TouchInterceptor mTouchInterceptor;
private final Paint mClipPaint = new Paint();
private int mBottomClip;
private final Paint mPaint = new Paint();
private LinearGradient mShader;
public ProfileBannerImageView(final Context context) {
this(context, null);
}
public ProfileBannerImageView(final Context context) {
this(context, null);
}
public ProfileBannerImageView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ProfileBannerImageView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ProfileBannerImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode()) return;
public ProfileBannerImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode()) return;
ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, null);
setScaleType(ScaleType.CENTER_CROP);
ViewCompat.setLayerType(this, LAYER_TYPE_SOFTWARE, null);
final boolean is_dark_theme = ThemeUtils.isDarkTheme(context);
COLORS_REVERSED[1] = is_dark_theme ? 0xFF000000 : 0xFFFFFFFF;
setForeground(ThemeUtils.getImageHighlightDrawable(context));
}
// setForeground(ThemeUtils.getImageHighlightDrawable(context));
mClipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
@Override
public final boolean dispatchTouchEvent(final MotionEvent event) {
if (mTouchInterceptor != null) {
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
if (ret) return true;
}
return super.dispatchTouchEvent(event);
}
@Override
public boolean hasOverlappingRendering() {
return true;
}
@Override
public final boolean onTouchEvent(final MotionEvent event) {
if (mTouchInterceptor != null) {
final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
if (ret) return true;
}
return super.onTouchEvent(event);
}
@Override
public final boolean dispatchTouchEvent(@NonNull final MotionEvent event) {
if (mTouchInterceptor != null) {
final boolean ret = mTouchInterceptor.dispatchTouchEvent(this, event);
if (ret) return true;
}
return super.dispatchTouchEvent(event);
}
@Override
public final void setOnSizeChangedListener(final OnSizeChangedListener listener) {
mOnSizeChangedListener = listener;
}
@Override
public final boolean onTouchEvent(@NonNull final MotionEvent event) {
if (mTouchInterceptor != null) {
final boolean ret = mTouchInterceptor.onTouchEvent(this, event);
if (ret) return true;
}
return super.onTouchEvent(event);
}
@Override
public final void setTouchInterceptor(final TouchInterceptor listener) {
mTouchInterceptor = listener;
}
@Override
public final void setOnSizeChangedListener(final OnSizeChangedListener listener) {
mOnSizeChangedListener = listener;
}
@Override
protected void onDraw(final Canvas canvas) {
if (isInEditMode()) return;
final int width = getWidth(), height = getHeight();
if (mShader == null) return;
super.onDraw(canvas);
mPaint.setShader(mShader);
mPaint.setXfermode(DST_IN);
canvas.drawRect(0, 0, width, height, mPaint);
}
@Override
public final void setTouchInterceptor(final TouchInterceptor listener) {
mTouchInterceptor = listener;
}
@SuppressLint("DrawAllocation")
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final int width = MeasureSpec.getSize(widthMeasureSpec), height = width / 3;
setMeasuredDimension(width, height);
if (width > 0) {
mShader = new LinearGradient(width / 2, 0, width / 2, height, COLORS, POSITIONS, Shader.TileMode.CLAMP);
}
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final int width = MeasureSpec.getSize(widthMeasureSpec), height = width / 2;
setMeasuredDimension(width, height);
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
@Override
protected final void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mOnSizeChangedListener != null) {
mOnSizeChangedListener.onSizeChanged(this, w, h, oldw, oldh);
}
}
@Override
protected final void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mOnSizeChangedListener != null) {
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 final ImageView profile_image;
public final TextView name, screen_name;
public final CheckBox checkbox;
private final ColorLabelRelativeLayout content;
private final View default_indicator;
public final ImageView profile_image;
public final TextView name, screen_name;
public final CheckBox checkbox;
private final ColorLabelRelativeLayout content;
private final View default_indicator;
private final View drag_handle;
public AccountViewHolder(final View view) {
content = (ColorLabelRelativeLayout) view;
name = (TextView) view.findViewById(android.R.id.text1);
screen_name = (TextView) view.findViewById(android.R.id.text2);
profile_image = (ImageView) view.findViewById(android.R.id.icon);
default_indicator = view.findViewById(R.id.default_indicator);
checkbox = (CheckBox) view.findViewById(android.R.id.checkbox);
}
public AccountViewHolder(final View view) {
content = (ColorLabelRelativeLayout) view;
name = (TextView) view.findViewById(android.R.id.text1);
screen_name = (TextView) view.findViewById(android.R.id.text2);
profile_image = (ImageView) view.findViewById(android.R.id.icon);
default_indicator = view.findViewById(R.id.default_indicator);
checkbox = (CheckBox) view.findViewById(android.R.id.checkbox);
drag_handle = view.findViewById(R.id.drag_handle);
}
public void setAccountColor(final int color) {
content.drawEnd(color);
}
public void setAccountColor(final int color) {
content.drawEnd(color);
}
public void setIsDefault(final boolean is_default) {
default_indicator.setVisibility(is_default ? View.VISIBLE : View.GONE);
}
public void setSortEnabled(boolean enabled) {
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;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
@ -32,198 +34,202 @@ import android.view.View;
public interface IForegroundView {
/**
* Returns the drawable used as the foreground of this FrameLayout. The
* foreground drawable, if non-null, is always drawn on top of the children.
*
* @return A Drawable or null if no foreground was set.
*/
public Drawable getForeground();
/**
* Returns the drawable used as the foreground of this FrameLayout. The
* foreground drawable, if non-null, is always drawn on top of the children.
*
* @return A Drawable or null if no foreground was set.
*/
public Drawable getForeground();
/**
* 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
* account by ensuring that the children are inset to be placed inside of
* the padding area.
*
* @param drawable The Drawable to be drawn on top of the children.
*
* @attr ref android.R.attr#foreground
*/
public void setForeground(final Drawable drawable);
/**
* 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
* account by ensuring that the children are inset to be placed inside of
* the padding area.
*
* @param drawable The Drawable to be drawn on top of the children.
* @attr ref android.R.attr#foreground
*/
public void setForeground(final Drawable drawable);
/**
* Describes how the foreground is positioned. Defaults to START and TOP.
*
* @param foregroundGravity See {@link android.view.Gravity}
*
* @attr ref android.R.attr#foregroundGravity
*/
public void setForegroundGravity(int foregroundGravity);
/**
* Describes how the foreground is positioned. Defaults to START and TOP.
*
* @param foregroundGravity See {@link android.view.Gravity}
* @attr ref android.R.attr#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 mOverlayBounds = new Rect();
private final Rect mSelfBounds = new Rect();
private final Rect mOverlayBounds = new Rect();
private Drawable mForeground;
private Drawable mForeground;
private int mForegroundGravity = Gravity.FILL;
private boolean mForegroundInPadding = true;
private boolean mForegroundBoundsChanged = false;
private int mForegroundGravity = Gravity.FILL;
private boolean mForegroundInPadding = true;
private boolean mForegroundBoundsChanged = false;
public ForegroundViewHelper(final View view, final Context context, final AttributeSet attrs, final int defStyle) {
mView = view;
final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.foreground,
android.R.attr.foregroundGravity }, defStyle, 0);
public ForegroundViewHelper(final View view, final Context context, final AttributeSet attrs, final int defStyle) {
mView = view;
final TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.foreground,
android.R.attr.foregroundGravity}, defStyle, 0);
mForegroundGravity = a.getInt(1, mForegroundGravity);
mForegroundGravity = a.getInt(1, mForegroundGravity);
final Drawable d = a.getDrawable(0);
if (d != null) {
setForeground(d);
}
final Drawable d = a.getDrawable(0);
if (d != null) {
setForeground(d);
}
mForegroundInPadding = true;
mForegroundInPadding = true;
a.recycle();
}
a.recycle();
}
public void dispatchOnDraw(final Canvas canvas) {
if (mForeground != null) {
final Drawable foreground = mForeground;
public void dispatchOnDraw(final Canvas canvas) {
if (mForeground != null) {
final Drawable foreground = mForeground;
if (mForegroundBoundsChanged) {
mForegroundBoundsChanged = false;
final Rect selfBounds = mSelfBounds;
final Rect overlayBounds = mOverlayBounds;
if (mForegroundBoundsChanged) {
mForegroundBoundsChanged = false;
final Rect selfBounds = mSelfBounds;
final Rect overlayBounds = mOverlayBounds;
final int w = mView.getRight() - mView.getLeft();
final int h = mView.getBottom() - mView.getTop();
final int w = mView.getRight() - mView.getLeft();
final int h = mView.getBottom() - mView.getTop();
if (mForegroundInPadding) {
selfBounds.set(0, 0, w, h);
} else {
selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h
- mView.getPaddingBottom());
}
if (mForegroundInPadding) {
selfBounds.set(0, 0, w, h);
} else {
selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h
- mView.getPaddingBottom());
}
final int layoutDirection = ViewCompat.getLayoutDirection(mView);
GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection);
foreground.setBounds(overlayBounds);
}
final int layoutDirection = ViewCompat.getLayoutDirection(mView);
GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection);
foreground.setBounds(overlayBounds);
}
foreground.draw(canvas);
}
}
foreground.draw(canvas);
}
}
public void dispatchOnLayout(final boolean changed, final int left, final int top, final int right,
final int bottom) {
mForegroundBoundsChanged = true;
}
public void dispatchOnLayout(final boolean changed, final int left, final int top, final int right,
final int bottom) {
mForegroundBoundsChanged = true;
}
public void dispatchOnSizeChanged(final int w, final int h, final int oldw, final int oldh) {
mForegroundBoundsChanged = true;
}
public void dispatchOnSizeChanged(final int w, final int h, final int oldw, final int oldh) {
mForegroundBoundsChanged = true;
}
public void draw(final Canvas canvas) {
if (mForeground != null) {
final Drawable foreground = mForeground;
public void draw(final Canvas canvas) {
if (mForeground != null) {
final Drawable foreground = mForeground;
if (mForegroundBoundsChanged) {
mForegroundBoundsChanged = false;
final Rect selfBounds = mSelfBounds;
final Rect overlayBounds = mOverlayBounds;
if (mForegroundBoundsChanged) {
mForegroundBoundsChanged = false;
final Rect selfBounds = mSelfBounds;
final Rect overlayBounds = mOverlayBounds;
final int w = mView.getRight() - mView.getLeft();
final int h = mView.getBottom() - mView.getTop();
final int w = mView.getRight() - mView.getLeft();
final int h = mView.getBottom() - mView.getTop();
if (mForegroundInPadding) {
selfBounds.set(0, 0, w, h);
} else {
selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h
- mView.getPaddingBottom());
}
if (mForegroundInPadding) {
selfBounds.set(0, 0, w, h);
} else {
selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h
- mView.getPaddingBottom());
}
final int layoutDirection = ViewCompat.getLayoutDirection(mView);
GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection);
foreground.setBounds(overlayBounds);
}
final int layoutDirection = ViewCompat.getLayoutDirection(mView);
GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection);
foreground.setBounds(overlayBounds);
}
foreground.draw(canvas);
}
}
foreground.draw(canvas);
}
}
public void drawableStateChanged() {
if (mForeground != null && mForeground.isStateful()) {
mForeground.setState(mView.getDrawableState());
}
}
public void drawableStateChanged() {
if (mForeground != null && mForeground.isStateful()) {
mForeground.setState(mView.getDrawableState());
}
}
public Drawable getForeground() {
return mForeground;
}
public Drawable getForeground() {
return mForeground;
}
public void jumpDrawablesToCurrentState() {
if (mForeground != null) {
mForeground.jumpToCurrentState();
}
}
public void jumpDrawablesToCurrentState() {
if (mForeground != null) {
mForeground.jumpToCurrentState();
}
}
public void setForeground(final Drawable drawable) {
if (mForeground != drawable) {
if (mForeground != null) {
mForeground.setCallback(null);
mView.unscheduleDrawable(mForeground);
}
public void setForeground(final Drawable drawable) {
if (mForeground != drawable) {
if (mForeground != null) {
mForeground.setCallback(null);
mView.unscheduleDrawable(mForeground);
}
mForeground = drawable;
mForeground = drawable;
if (drawable != null) {
drawable.setCallback(mView);
if (drawable.isStateful()) {
drawable.setState(mView.getDrawableState());
}
if (mForegroundGravity == Gravity.FILL) {
final Rect padding = new Rect();
if (drawable.getPadding(padding)) {
}
}
}
mView.requestLayout();
mView.invalidate();
}
}
if (drawable != null) {
drawable.setCallback(mView);
if (drawable.isStateful()) {
drawable.setState(mView.getDrawableState());
}
if (mForegroundGravity == Gravity.FILL) {
final Rect padding = new Rect();
if (drawable.getPadding(padding)) {
}
}
}
mView.requestLayout();
mView.invalidate();
}
}
public void setForegroundGravity(int foregroundGravity) {
if (mForegroundGravity != foregroundGravity) {
if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
foregroundGravity |= Gravity.START;
}
public void setForegroundGravity(int foregroundGravity) {
if (mForegroundGravity != foregroundGravity) {
if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
foregroundGravity |= Gravity.START;
}
if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
foregroundGravity |= Gravity.TOP;
}
if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
foregroundGravity |= Gravity.TOP;
}
mForegroundGravity = foregroundGravity;
mForegroundGravity = foregroundGravity;
if (mForegroundGravity == Gravity.FILL && mForeground != null) {
final Rect padding = new Rect();
if (mForeground.getPadding(padding)) {
}
} else {
}
if (mForegroundGravity == Gravity.FILL && mForeground != null) {
final Rect padding = new Rect();
if (mForeground.getPadding(padding)) {
}
} else {
}
mView.requestLayout();
}
}
mView.requestLayout();
}
}
public boolean verifyDrawable(final Drawable who) {
return who == mForeground;
}
}
public boolean verifyDrawable(final Drawable who) {
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"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ScrollView
android:layout_width="match_parent"
@ -28,7 +27,7 @@
android:hint="@string/username"
android:inputType="textEmailAddress"
android:singleLine="true"
android:typeface="normal" />
android:typeface="normal"/>
<EditText
android:id="@+id/password"
@ -39,7 +38,7 @@
android:hint="@string/password"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="normal" />
android:typeface="normal"/>
</LinearLayout>
<LinearLayout
@ -58,7 +57,7 @@
android:layout_weight="1"
android:minHeight="48dp"
android:onClick="onClick"
android:text="@string/sign_in" />
android:text="@string/sign_in"/>
<Button
android:id="@+id/sign_up"
@ -68,7 +67,7 @@
android:layout_weight="1"
android:minHeight="48dp"
android:onClick="onClick"
android:text="@string/sign_up" />
android:text="@string/sign_up"/>
</LinearLayout>
<Button
@ -83,18 +82,8 @@
android:minHeight="36dp"
android:onClick="onClick"
android:text="@string/sign_in_method_introduction_title"
android:textAppearance="?android:textAppearanceSmall" />
android:textAppearance="?android:textAppearanceSmall"/>
</RelativeLayout>
</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>

View File

@ -18,8 +18,10 @@
android:layout_weight="0"
android:gravity="center_vertical"
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
android:id="@+id/alpha_slider"

View File

@ -9,7 +9,7 @@
android:id="@+id/left_drawer"
android:layout_width="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"/>
</org.mariotaku.twidere.view.LeftDrawerFrameLayout>

View File

@ -1,300 +1,300 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/header_user_profile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/header_user_profile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<org.mariotaku.twidere.view.HalfWidthSpace
android:id="@+id/profile_banner_space"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Space
android:id="@+id/profile_banner_space"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/element_spacing_xsmall"
android:layout_above="@+id/profile_name_container"
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"/>
-->
<View
android:layout_width="match_parent"
android:layout_height="@dimen/element_spacing_xsmall"
android:layout_above="@+id/profile_name_container"
android:background="@drawable/shadow_top"/>
<FrameLayout
android:id="@+id/profile_image_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/profile_name_container"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:background="?cardItemBackground">
<!--<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"/>-->
<org.mariotaku.twidere.view.ProfileImageView
android:id="@+id/profile_image"
android:layout_width="@dimen/icon_size_user_profile"
android:layout_height="@dimen/icon_size_user_profile"
android:contentDescription="@string/profile_image"
android:scaleType="centerCrop"
android:src="@drawable/ic_profile_image_default"/>
</FrameLayout>
<FrameLayout
android:id="@+id/profile_image_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/profile_name_container"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:background="?cardItemBackground">
<org.mariotaku.twidere.view.ColorLabelLinearLayout
android:id="@+id/profile_name_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/profile_banner_space"
android:layout_toRightOf="@+id/profile_image_container"
android:background="?android:selectableItemBackground"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small"
app:ignorePadding="true">
<org.mariotaku.twidere.view.ProfileImageView
android:id="@+id/profile_image"
android:layout_width="@dimen/icon_size_user_profile"
android:layout_height="@dimen/icon_size_user_profile"
android:contentDescription="@string/profile_image"
android:scaleType="centerCrop"
android:src="@drawable/ic_profile_image_default"/>
</FrameLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/name"
android:textAppearance="?android:textAppearanceMedium"/>
<org.mariotaku.twidere.view.ColorLabelLinearLayout
android:id="@+id/profile_name_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/profile_banner_space"
android:layout_toRightOf="@+id/profile_image_container"
android:background="?android:selectableItemBackground"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small"
app:ignorePadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/name"
android:textAppearance="?android:textAppearanceMedium"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/screen_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/screen_name"
android:textAppearance="?android:textAppearanceSmall"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/following_you_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:singleLine="true"
android:text="@string/following_you"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorTertiary"
android:visibility="gone"/>
</LinearLayout>
</org.mariotaku.twidere.view.ColorLabelLinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/screen_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/screen_name"
android:textAppearance="?android:textAppearanceSmall"/>
<org.mariotaku.twidere.view.CardItemLinearLayout
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/profile_name_container"
android:orientation="vertical"
android:padding="@dimen/element_spacing_normal"
android:splitMotionEvents="false">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/following_you_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:singleLine="true"
android:text="@string/following_you"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorTertiary"
android:visibility="gone"/>
</LinearLayout>
</org.mariotaku.twidere.view.ColorLabelLinearLayout>
<LinearLayout
android:id="@+id/description_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.CardItemLinearLayout
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/profile_name_container"
android:orientation="vertical"
android:padding="@dimen/element_spacing_normal"
android:splitMotionEvents="false">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/description"
android:textAppearance="?android:textAppearanceMedium"/>
<LinearLayout
android:id="@+id/description_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/description"
android:textAppearance="?android:textAppearanceMedium"/>
<LinearLayout
android:id="@+id/location_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/location"
android:textAppearance="?android:textAppearanceMedium"/>
<LinearLayout
android:id="@+id/location_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/location"
android:textAppearance="?android:textAppearanceMedium"/>
<LinearLayout
android:id="@+id/url_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/url"
android:textAppearance="?android:textAppearanceMedium"/>
<LinearLayout
android:id="@+id/url_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/url"
android:textAppearance="?android:textAppearanceMedium"/>
<LinearLayout
android:id="@+id/created_at_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/created_at"
android:textAppearance="?android:textAppearanceMedium"/>
<LinearLayout
android:id="@+id/created_at_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/created_at"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/created_at"
android:textAppearance="?android:textAppearanceMedium"/>
<View
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:background="@color/divider_color"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/created_at"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/action_button_size"
android:baselineAligned="false"
android:divider="@drawable/divider_vertical_small_holo"
android:orientation="horizontal"
android:showDividers="middle"
android:splitMotionEvents="false">
<View
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:background="@color/divider_color"/>
<LinearLayout
android:id="@+id/tweets_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/action_button_size"
android:baselineAligned="false"
android:divider="@drawable/divider_vertical_small_holo"
android:orientation="horizontal"
android:showDividers="middle"
android:splitMotionEvents="false">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/statuses_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<LinearLayout
android:id="@+id/tweets_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/statuses"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/statuses_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<LinearLayout
android:id="@+id/followers_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/statuses"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/followers_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<LinearLayout
android:id="@+id/followers_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/followers"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/followers_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<LinearLayout
android:id="@+id/friends_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/followers"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/friends_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<LinearLayout
android:id="@+id/friends_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
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>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/friends_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
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>

View File

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<org.mariotaku.twidere.view.ProfileBannerImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/profile_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:scaleType="centerCrop"/>
<org.mariotaku.twidere.view.ProfileBannerImageView
android:id="@+id/profile_banner"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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:textAppearance="?android:attr/textAppearanceSmall"/>
<ImageButton
<org.mariotaku.twidere.view.ActionIconView
android:id="@+id/api_url_format_help"
android:layout_width="@dimen/element_size_small"
android:layout_height="@dimen/element_size_small"
android:src="@drawable/ic_action_info"
android:layout_weight="0"
android:background="?android:selectableItemBackground"/>
</LinearLayout>

View File

@ -1,11 +1,15 @@
<?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:text="- Mea est luna -"
android:gravity="center"
android:textColor="?android:textColorPrimary"
android:layout_height="wrap_content"
android:alpha="0.2"
android:textSize="8sp"
android:typeface="serif"
app:fontPath="fonts/LibreBaskerville-Italic.ttf"
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:layout_height="wrap_content" />
android:typeface="serif"/>

View File

@ -67,7 +67,6 @@
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/default_indicator"
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>
<declare-styleable name="Twidere">
<attr name="cardItemBackground" format="reference" />
<attr name="cardItemBackgroundColor" format="color" />
<attr name="cardItemMessageIncomingBackground" format="reference" />
<attr name="cardItemMessageOutgoingBackground" format="reference" />
<attr name="cardItemMessageProfileImageIncomingBackground" format="reference" />
<attr name="cardItemMessageProfileImageOutgoingBackground" format="reference" />
<attr name="listMenuOverflowButton" format="reference" />
<attr name="ignorePadding" format="boolean" />
<attr name="linePageIndicatorStyle" format="reference" />
<attr name="cardItemViewStyle" format="reference" />
<attr name="staggeredGridViewStyle" format="reference" />
<attr name="cardItemBackground" format="reference"/>
<attr name="cardItemBackgroundColor" format="color"/>
<attr name="cardItemMessageIncomingBackground" format="reference"/>
<attr name="cardItemMessageOutgoingBackground" format="reference"/>
<attr name="cardItemMessageProfileImageIncomingBackground" format="reference"/>
<attr name="cardItemMessageProfileImageOutgoingBackground" format="reference"/>
<attr name="listMenuOverflowButton" format="reference"/>
<attr name="ignorePadding" format="boolean"/>
<attr name="linePageIndicatorStyle" format="reference"/>
<attr name="cardItemViewStyle" format="reference"/>
<attr name="staggeredGridViewStyle" format="reference"/>
</declare-styleable>
<declare-styleable name="CardItemView">
<attr name="cardBackground" format="reference" />
<attr name="cardSelector" format="reference" />
<attr name="cardActivatedIndicator" format="reference" />
<attr name="cardOverflowIcon" format="reference" />
<attr name="cardBackgroundAlpha" format="fraction" />
<attr name="cardGapHeight" format="dimension" />
<attr name="cardGapText" format="string" />
<attr name="cardGapTextColor" format="color" />
<attr name="cardGapTextSize" format="dimension" />
<attr name="cardBackground" format="reference"/>
<attr name="cardSelector" format="reference"/>
<attr name="cardActivatedIndicator" format="reference"/>
<attr name="cardOverflowIcon" format="reference"/>
<attr name="cardBackgroundAlpha" format="fraction"/>
<attr name="cardGapHeight" format="dimension"/>
<attr name="cardGapText" format="string"/>
<attr name="cardGapTextColor" format="color"/>
<attr name="cardGapTextSize" format="dimension"/>
</declare-styleable>
<declare-styleable name="TabPagerIndicator">
<attr name="tabItemStyle" format="reference" />
<attr name="tabItemContentStyle" format="reference" />
<attr name="tabItemTextStyle" format="reference" />
<attr name="tabItemStyle" format="reference"/>
<attr name="tabItemContentStyle" format="reference"/>
<attr name="tabItemTextStyle" format="reference"/>
</declare-styleable>
<declare-styleable name="LinePageIndicator">
<!-- 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. -->
<attr name="unselectedColor" format="color" />
<attr name="unselectedColor" format="color"/>
<!-- 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. -->
<attr name="lineWidth" format="dimension" />
<attr name="lineWidth" format="dimension"/>
<!-- 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. -->
<attr name="gapWidth" format="dimension" />
<attr name="gapWidth" format="dimension"/>
<!-- View background -->
<attr name="android:background" />
<attr name="android:background"/>
</declare-styleable>
<declare-styleable name="ValueDependencyPreference">
<attr name="dependencyKey" format="string" />
<attr name="dependencyValues" format="reference" />
<attr name="dependencyValueDefault" format="string" />
<attr name="dependencyKey" format="string"/>
<attr name="dependencyValues" format="reference"/>
<attr name="dependencyValueDefault" format="string"/>
</declare-styleable>
<declare-styleable name="AccountsListPreference">
<attr name="switchKey" format="string" />
<attr name="switchDefault" format="boolean" />
<attr name="switchKey" format="string"/>
<attr name="switchDefault" format="boolean"/>
</declare-styleable>
<declare-styleable name="NotificationTypePreference">
<attr name="notificationType" />
<attr name="notificationType"/>
</declare-styleable>
<declare-styleable name="SeekBarDialogPreference">
<attr name="max" format="integer" />
<attr name="min" format="integer" />
<attr name="progressTextSuffix" format="string" />
<attr name="max" format="integer"/>
<attr name="min" format="integer"/>
<attr name="step" format="integer"/>
<attr name="progressTextSuffix" format="string"/>
</declare-styleable>
<declare-styleable name="AssetFontTextView">
<attr name="fontPath" format="string"/>
</declare-styleable>
<attr name="notificationType">
<flag name="none" value="0" />
<flag name="ringtone" value="1" />
<flag name="vibration" value="2" />
<flag name="light" value="4" />
<flag name="none" value="0"/>
<flag name="ringtone" value="1"/>
<flag name="vibration" value="2"/>
<flag name="light" value="4"/>
</attr>
</resources>

View File

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