org.getlantern.firetweet.activity.support.UserProfileEditorActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.getlantern.firetweet.activity.support.UserProfileEditorActivity.java

Source

/*
 *             Firetweet - 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.getlantern.firetweet.activity.support;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import org.getlantern.firetweet.R;
import org.getlantern.firetweet.app.FiretweetApplication;
import org.getlantern.firetweet.fragment.support.SupportProgressDialogFragment;
import org.getlantern.firetweet.loader.support.ParcelableUserLoader;
import org.getlantern.firetweet.model.ParcelableUser;
import org.getlantern.firetweet.model.SingleResponse;
import org.getlantern.firetweet.util.AsyncTaskManager;
import org.getlantern.firetweet.util.AsyncTaskUtils;
import org.getlantern.firetweet.util.AsyncTwitterWrapper.UpdateProfileBannerImageTask;
import org.getlantern.firetweet.util.AsyncTwitterWrapper.UpdateProfileImageTask;
import org.getlantern.firetweet.util.MediaLoaderWrapper;
import org.getlantern.firetweet.util.ParseUtils;
import org.getlantern.firetweet.util.ThemeUtils;
import org.getlantern.firetweet.util.TwitterWrapper;
import org.getlantern.firetweet.util.accessor.ViewAccessor;
import org.getlantern.firetweet.view.ForegroundColorView;
import org.getlantern.firetweet.view.iface.IExtendedView.OnSizeChangedListener;

import java.io.File;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.User;

import static android.text.TextUtils.isEmpty;
import static org.getlantern.firetweet.util.Utils.createPickImageIntent;
import static org.getlantern.firetweet.util.Utils.createTakePhotoIntent;
import static org.getlantern.firetweet.util.Utils.getTwitterInstance;
import static org.getlantern.firetweet.util.Utils.isMyAccount;
import static org.getlantern.firetweet.util.Utils.showErrorMessage;

public class UserProfileEditorActivity extends BaseActionBarActivity implements OnSizeChangedListener, TextWatcher,
        OnClickListener, LoaderCallbacks<SingleResponse<ParcelableUser>> {

    private static final int LOADER_ID_USER = 1;

    private static final int REQUEST_UPLOAD_PROFILE_IMAGE = 1;
    private static final int REQUEST_UPLOAD_PROFILE_BANNER_IMAGE = 2;
    private static final int REQUEST_PICK_LINK_COLOR = 3;
    private static final int REQUEST_PICK_BACKGROUND_COLOR = 4;

    private MediaLoaderWrapper mLazyImageLoader;
    private AsyncTaskManager mAsyncTaskManager;
    private AsyncTask<Object, Object, ?> mTask;

    private ImageView mProfileImageView;
    private ImageView mProfileBannerView;
    private EditText mEditName, mEditDescription, mEditLocation, mEditUrl;
    private View mProgressContainer, mContent;
    private View mProfileImageCamera, mProfileImageGallery;
    private View mProfileBannerGallery, mProfileBannerRemove;
    private View mActionBarOverlay;
    private View mCancelButton, mDoneButton;
    private View mSetLinkColor, mSetBackgroundColor;
    private ForegroundColorView mLinkColor, mBackgroundColor;

    private long mAccountId;
    private ParcelableUser mUser;

    private boolean mUserInfoLoaderInitialized;

    private boolean mGetUserInfoCalled;
    private Toolbar mToolbar;

    @Override
    public void beforeTextChanged(final CharSequence s, final int length, final int start, final int end) {
    }

    @Override
    public void onTextChanged(final CharSequence s, final int length, final int start, final int end) {
        updateDoneButton();
    }

    @Override
    public void afterTextChanged(final Editable s) {
    }

    @Override
    public int getThemeResourceId() {
        return ThemeUtils.getNoActionBarThemeResource(this);
    }

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Intent intent = getIntent();
        final long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
        if (!isMyAccount(this, accountId)) {
            finish();
            return;
        }
        mAsyncTaskManager = FiretweetApplication.getInstance(this).getAsyncTaskManager();
        mLazyImageLoader = FiretweetApplication.getInstance(this).getMediaLoaderWrapper();
        mAccountId = accountId;

        setContentView(R.layout.activity_user_profile_editor);
        setSupportActionBar(mToolbar);
        ViewAccessor.setBackground(mActionBarOverlay, ThemeUtils.getWindowContentOverlay(this));
        ViewAccessor.setBackground(mToolbar,
                ThemeUtils.getActionBarBackground(mToolbar.getContext(), getCurrentThemeResourceId()));
        // setOverrideExitAniamtion(false);
        mEditName.addTextChangedListener(this);
        mEditDescription.addTextChangedListener(this);
        mEditLocation.addTextChangedListener(this);
        mEditUrl.addTextChangedListener(this);
        mProfileImageView.setOnClickListener(this);
        mProfileBannerView.setOnClickListener(this);
        mProfileImageCamera.setOnClickListener(this);
        mProfileImageGallery.setOnClickListener(this);
        mProfileBannerGallery.setOnClickListener(this);
        mProfileBannerRemove.setOnClickListener(this);
        mCancelButton.setOnClickListener(this);
        mDoneButton.setOnClickListener(this);
        mSetLinkColor.setOnClickListener(this);
        mSetBackgroundColor.setOnClickListener(this);

        if (savedInstanceState != null && savedInstanceState.getParcelable(EXTRA_USER) != null) {
            final ParcelableUser user = savedInstanceState.getParcelable(EXTRA_USER);
            displayUser(user);
            mEditName.setText(savedInstanceState.getString(EXTRA_NAME, user.name));
            mEditLocation.setText(savedInstanceState.getString(EXTRA_LOCATION, user.location));
            mEditDescription.setText(savedInstanceState.getString(EXTRA_DESCRIPTION, user.description_expanded));
            mEditUrl.setText(savedInstanceState.getString(EXTRA_URL, user.url_expanded));
        } else {
            getUserInfo();
        }
    }

    @Override
    protected void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable(EXTRA_USER, mUser);
        outState.putString(EXTRA_NAME, ParseUtils.parseString(mEditName.getText()));
        outState.putString(EXTRA_DESCRIPTION, ParseUtils.parseString(mEditDescription.getText()));
        outState.putString(EXTRA_LOCATION, ParseUtils.parseString(mEditLocation.getText()));
        outState.putString(EXTRA_URL, ParseUtils.parseString(mEditUrl.getText()));
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    public void onClick(final View view) {
        final ParcelableUser user = mUser;
        if (user == null || (mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING))
            return;
        switch (view.getId()) {
        case R.id.profile_image: {
            break;
        }
        case R.id.profile_banner: {
            break;
        }
        case R.id.profile_image_camera: {
            final Uri uri = createTempFileUri();
            final Intent intent = createTakePhotoIntent(uri, null, null, 1, 1, true);
            mTask = new UpdateProfileImageTaskInternal(this, mAsyncTaskManager, mAccountId, uri, true);
            startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
            break;
        }
        case R.id.profile_image_gallery: {
            final Uri uri = createTempFileUri();
            final Intent intent = createPickImageIntent(uri, null, null, 1, 1, true);
            mTask = new UpdateProfileImageTaskInternal(this, mAsyncTaskManager, mAccountId, uri, true);
            startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
            break;
        }
        case R.id.profile_banner_gallery: {
            final Uri uri = createTempFileUri();
            final Intent intent = createPickImageIntent(uri, null, null, 2, 1, true);
            mTask = new UpdateProfileBannerImageTaskInternal(this, mAsyncTaskManager, mAccountId, uri, true);
            startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BANNER_IMAGE);
            break;
        }
        case R.id.profile_banner_remove: {
            mTask = new RemoveProfileBannerTaskInternal(user.account_id);
            AsyncTaskUtils.executeTask(mTask);
            break;
        }
        case R.id.actionbar_cancel: {
            finish();
            break;
        }
        case R.id.actionbar_done: {
            final String name = ParseUtils.parseString(mEditName.getText());
            final String url = ParseUtils.parseString(mEditUrl.getText());
            final String location = ParseUtils.parseString(mEditLocation.getText());
            final String description = ParseUtils.parseString(mEditDescription.getText());
            final int linkColor = mLinkColor.getColor();
            final int backgroundColor = mBackgroundColor.getColor();
            mTask = new UpdateProfileTaskInternal(this, mAccountId, mUser, name, url, location, description,
                    linkColor, backgroundColor);
            AsyncTaskUtils.executeTask(mTask);
            break;
        }
        case R.id.set_link_color: {
            final Intent intent = new Intent(this, ColorPickerDialogActivity.class);
            intent.putExtra(EXTRA_COLOR, user.link_color);
            intent.putExtra(EXTRA_ALPHA_SLIDER, false);
            startActivityForResult(intent, REQUEST_PICK_LINK_COLOR);
            break;
        }
        case R.id.set_background_color: {
            final Intent intent = new Intent(this, ColorPickerDialogActivity.class);
            intent.putExtra(EXTRA_COLOR, user.background_color);
            intent.putExtra(EXTRA_ALPHA_SLIDER, false);
            startActivityForResult(intent, REQUEST_PICK_BACKGROUND_COLOR);
            break;
        }
        }
    }

    @Override
    public Loader<SingleResponse<ParcelableUser>> onCreateLoader(final int id, final Bundle args) {
        mProgressContainer.setVisibility(View.VISIBLE);
        mContent.setVisibility(View.GONE);
        return new ParcelableUserLoader(UserProfileEditorActivity.this, mAccountId, mAccountId, null,
                getIntent().getExtras(), false, false);
    }

    @Override
    public void onLoadFinished(final Loader<SingleResponse<ParcelableUser>> loader,
            final SingleResponse<ParcelableUser> data) {
        if (data.getData() != null && data.getData().id > 0) {
            displayUser(data.getData());
        } else if (mUser == null) {
            finish();
        }
    }

    @Override
    public void onLoaderReset(final Loader<SingleResponse<ParcelableUser>> loader) {

    }

    @Override
    public void onSizeChanged(final View view, final int w, final int h, final int oldw, final int oldh) {
    }

    @Override
    public void onSupportContentChanged() {
        super.onSupportContentChanged();
        mToolbar = (Toolbar) findViewById(R.id.done_bar);
        mProgressContainer = findViewById(R.id.progress_container);
        mContent = findViewById(R.id.content);
        mProfileBannerView = (ImageView) findViewById(R.id.profile_banner);
        mProfileImageView = (ImageView) findViewById(R.id.profile_image);
        mEditName = (EditText) findViewById(R.id.name);
        mEditDescription = (EditText) findViewById(R.id.description);
        mEditLocation = (EditText) findViewById(R.id.location);
        mEditUrl = (EditText) findViewById(R.id.url);
        mActionBarOverlay = findViewById(R.id.actionbar_overlay);
        mProfileImageCamera = findViewById(R.id.profile_image_camera);
        mProfileImageGallery = findViewById(R.id.profile_image_gallery);
        mProfileBannerGallery = findViewById(R.id.profile_banner_gallery);
        mProfileBannerRemove = findViewById(R.id.profile_banner_remove);
        mLinkColor = (ForegroundColorView) findViewById(R.id.link_color);
        mBackgroundColor = (ForegroundColorView) findViewById(R.id.background_color);
        mCancelButton = findViewById(R.id.actionbar_cancel);
        mDoneButton = findViewById(R.id.actionbar_done);
        mSetLinkColor = findViewById(R.id.set_link_color);
        mSetBackgroundColor = findViewById(R.id.set_background_color);
    }

    @Override
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        if (resultCode == RESULT_CANCELED)
            return;
        switch (requestCode) {
        case REQUEST_UPLOAD_PROFILE_BANNER_IMAGE: {
            if (mTask == null || mTask.getStatus() != AsyncTask.Status.PENDING)
                return;
            AsyncTaskUtils.executeTask(mTask);
            break;
        }
        case REQUEST_UPLOAD_PROFILE_IMAGE: {
            if (mTask == null || mTask.getStatus() != AsyncTask.Status.PENDING)
                return;
            AsyncTaskUtils.executeTask(mTask);
            break;
        }
        case REQUEST_PICK_LINK_COLOR: {
            if (resultCode == ColorPickerDialogActivity.RESULT_OK) {
                mLinkColor.setColor(data.getIntExtra(EXTRA_COLOR, 0));
                updateDoneButton();
            }
            break;
        }
        case REQUEST_PICK_BACKGROUND_COLOR: {
            if (resultCode == ColorPickerDialogActivity.RESULT_OK) {
                mBackgroundColor.setColor(data.getIntExtra(EXTRA_COLOR, 0));
                updateDoneButton();
            }
            break;
        }
        }

    }

    boolean isProfileChanged() {
        final ParcelableUser user = mUser;
        if (user == null)
            return true;
        if (!stringEquals(mEditName.getText(), user.name))
            return true;
        if (!stringEquals(mEditDescription.getText(), user.description_expanded))
            return true;
        if (!stringEquals(mEditLocation.getText(), user.location))
            return true;
        if (!stringEquals(mEditUrl.getText(), isEmpty(user.url_expanded) ? user.url : user.url_expanded))
            return true;
        if (mLinkColor.getColor() != user.link_color)
            return true;
        if (mBackgroundColor.getColor() != user.background_color)
            return true;
        return false;
    }

    private Uri createTempFileUri() {
        final File cache_dir = getExternalCacheDir();
        final File file = new File(cache_dir, "tmp_image_" + System.currentTimeMillis());
        return Uri.fromFile(file);
    }

    private void displayUser(final ParcelableUser user) {
        if (!mGetUserInfoCalled)
            return;
        mGetUserInfoCalled = false;
        mUser = user;
        if (user != null) {
            mProgressContainer.setVisibility(View.GONE);
            mContent.setVisibility(View.VISIBLE);
            mEditName.setText(user.name);
            mEditDescription.setText(user.description_expanded);
            mEditLocation.setText(user.location);
            mEditUrl.setText(isEmpty(user.url_expanded) ? user.url : user.url_expanded);
            mLazyImageLoader.displayProfileImage(mProfileImageView, user.profile_image_url);
            final int def_width = getResources().getDisplayMetrics().widthPixels;
            mLazyImageLoader.displayProfileBanner(mProfileBannerView, user.profile_banner_url, def_width);
            mLinkColor.setColor(user.link_color);
            mBackgroundColor.setColor(user.background_color);
        } else {
            mProgressContainer.setVisibility(View.GONE);
            mContent.setVisibility(View.GONE);
        }
        updateDoneButton();
    }

    private void getUserInfo() {
        final LoaderManager lm = getSupportLoaderManager();
        lm.destroyLoader(LOADER_ID_USER);
        mGetUserInfoCalled = true;
        if (mUserInfoLoaderInitialized) {
            lm.restartLoader(LOADER_ID_USER, null, this);
        } else {
            lm.initLoader(LOADER_ID_USER, null, this);
            mUserInfoLoaderInitialized = true;
        }
    }

    private void setUpdateState(final boolean start) {
        mEditName.setEnabled(!start);
        mEditDescription.setEnabled(!start);
        mEditLocation.setEnabled(!start);
        mEditUrl.setEnabled(!start);
        mProfileImageView.setEnabled(!start);
        mProfileImageView.setOnClickListener(start ? null : this);
        mProfileBannerView.setEnabled(!start);
        mProfileBannerView.setOnClickListener(start ? null : this);
        invalidateOptionsMenu();
    }

    private static boolean stringEquals(final CharSequence str1, final CharSequence str2) {
        if (str1 == null || str2 == null)
            return str1 == str2;
        if (str1.length() != str2.length())
            return false;
        for (int i = 0, j = str1.length(); i < j; i++) {
            if (str1.charAt(i) != str2.charAt(i))
                return false;
        }
        return true;
    }

    private void updateDoneButton() {
        mDoneButton.setEnabled(isProfileChanged());
    }

    static class UpdateProfileTaskInternal extends AsyncTask<Object, Object, SingleResponse<ParcelableUser>> {

        private static final String DIALOG_FRAGMENT_TAG = "updating_user_profile";
        private final UserProfileEditorActivity mActivity;
        private final Handler mHandler;
        private final long mAccountId;
        private final ParcelableUser mOriginal;
        private final String mName;
        private final String mUrl;
        private final String mLocation;
        private final String mDescription;
        private final int mLinkColor;
        private final int mBackgroundColor;

        public UpdateProfileTaskInternal(final UserProfileEditorActivity activity, final long accountId,
                final ParcelableUser original, final String name, final String url, final String location,
                final String description, final int linkColor, final int backgroundColor) {
            mActivity = activity;
            mHandler = new Handler(activity.getMainLooper());
            mAccountId = accountId;
            mOriginal = original;
            mName = name;
            mUrl = url;
            mLocation = location;
            mDescription = description;
            mLinkColor = linkColor;
            mBackgroundColor = backgroundColor;
        }

        @Override
        protected SingleResponse<ParcelableUser> doInBackground(final Object... params) {
            final Twitter twitter = getTwitterInstance(mActivity, mAccountId, true);
            try {
                User user = null;
                if (isColorChanged()) {
                    final String linkColor = String.format("%08x", mLinkColor).substring(2);
                    final String backgroundColor = String.format("%08x", mBackgroundColor).substring(2);
                    user = twitter.updateProfileColors(backgroundColor, null, linkColor, null, null);
                }
                if (isProfileChanged()) {
                    user = twitter.updateProfile(mName, mUrl, mLocation, mDescription);
                }
                if (user == null) {
                    // User profile unchanged
                    return SingleResponse.getInstance();
                }
                return SingleResponse.getInstance(new ParcelableUser(user, mAccountId));
            } catch (TwitterException e) {
                return SingleResponse.getInstance(e);
            }
        }

        private boolean isColorChanged() {
            final ParcelableUser orig = mOriginal;
            if (orig == null)
                return true;
            if (mLinkColor != orig.link_color)
                return true;
            if (mBackgroundColor != orig.background_color)
                return true;
            return false;
        }

        private boolean isProfileChanged() {
            final ParcelableUser orig = mOriginal;
            if (orig == null)
                return true;
            if (!stringEquals(mName, orig.name))
                return true;
            if (!stringEquals(mDescription,
                    isEmpty(orig.description_expanded) ? orig.description_plain : orig.description_expanded))
                return true;
            if (!stringEquals(mLocation, orig.location))
                return true;
            if (!stringEquals(mUrl, isEmpty(orig.url_expanded) ? orig.url : orig.url_expanded))
                return true;
            return false;
        }

        @Override
        protected void onPostExecute(final SingleResponse<ParcelableUser> result) {
            super.onPostExecute(result);
            final Fragment f = mActivity.getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG);
            if (f instanceof DialogFragment) {
                ((DialogFragment) f).dismissAllowingStateLoss();
            }
        }

        @Override
        protected void onPreExecute() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    final DialogFragment df = SupportProgressDialogFragment.show(mActivity, DIALOG_FRAGMENT_TAG);
                    df.setCancelable(false);
                }
            });
            super.onPreExecute();
        }

    }

    class RemoveProfileBannerTaskInternal extends AsyncTask<Object, Object, SingleResponse<Boolean>> {

        private final long account_id;

        RemoveProfileBannerTaskInternal(final long account_id) {
            this.account_id = account_id;
        }

        @Override
        protected SingleResponse<Boolean> doInBackground(final Object... params) {
            return TwitterWrapper.deleteProfileBannerImage(UserProfileEditorActivity.this, account_id);
        }

        @Override
        protected void onPostExecute(final SingleResponse<Boolean> result) {
            super.onPostExecute(result);
            if (result.getData() != null && result.getData()) {
                getUserInfo();
                Toast.makeText(UserProfileEditorActivity.this, R.string.profile_banner_image_updated,
                        Toast.LENGTH_SHORT).show();
            } else {
                showErrorMessage(UserProfileEditorActivity.this, R.string.action_removing_profile_banner_image,
                        result.getException(), true);
            }
            setUpdateState(false);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            setUpdateState(true);
        }

    }

    private class UpdateProfileBannerImageTaskInternal extends UpdateProfileBannerImageTask {

        public UpdateProfileBannerImageTaskInternal(final Context context, final AsyncTaskManager manager,
                final long account_id, final Uri image_uri, final boolean delete_image) {
            super(context, manager, account_id, image_uri, delete_image);
        }

        @Override
        protected void onPostExecute(final SingleResponse<ParcelableUser> result) {
            super.onPostExecute(result);
            setUpdateState(false);
            getUserInfo();
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            setUpdateState(true);
        }

    }

    private class UpdateProfileImageTaskInternal extends UpdateProfileImageTask {

        public UpdateProfileImageTaskInternal(final Context context, final AsyncTaskManager manager,
                final long account_id, final Uri image_uri, final boolean delete_image) {
            super(context, manager, account_id, image_uri, delete_image);
        }

        @Override
        protected void onPostExecute(final SingleResponse<ParcelableUser> result) {
            super.onPostExecute(result);
            if (result != null && result.getData() != null) {
                displayUser(result.getData());
            }
            setUpdateState(false);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            setUpdateState(true);
        }

    }
}