de.vanita5.twittnuker.activity.support.UserProfileEditorActivity.java Source code

Java tutorial

Introduction

Here is the source code for de.vanita5.twittnuker.activity.support.UserProfileEditorActivity.java

Source

/*
 * Twittnuker - Twitter client for Android
 *
 * Copyright (C) 2013-2014 vanita5 <mail@vanita5.de>
 *
 * This program incorporates a modified version of Twidere.
 * 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 de.vanita5.twittnuker.activity.support;

import static android.text.TextUtils.isEmpty;
import static de.vanita5.twittnuker.util.Utils.createPickImageIntent;
import static de.vanita5.twittnuker.util.Utils.createTakePhotoIntent;
import static de.vanita5.twittnuker.util.Utils.isMyAccount;
import static de.vanita5.twittnuker.util.Utils.showErrorMessage;

import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import de.keyboardsurfer.android.widget.crouton.Crouton;
import de.keyboardsurfer.android.widget.crouton.CroutonLifecycleCallback;
import de.keyboardsurfer.android.widget.crouton.CroutonStyle;

import org.mariotaku.menucomponent.widget.PopupMenu;
import de.vanita5.twittnuker.R;
import de.vanita5.twittnuker.app.TwittnukerApplication;
import de.vanita5.twittnuker.loader.support.ParcelableUserLoader;
import de.vanita5.twittnuker.menu.TwidereMenuInflater;
import de.vanita5.twittnuker.model.ParcelableUser;
import de.vanita5.twittnuker.model.SingleResponse;
import de.vanita5.twittnuker.provider.TweetStore.Accounts;
import de.vanita5.twittnuker.task.AsyncTask;
import de.vanita5.twittnuker.task.AsyncTask.Status;
import de.vanita5.twittnuker.util.AsyncTaskManager;
import de.vanita5.twittnuker.util.AsyncTwitterWrapper.UpdateProfileBannerImageTask;
import de.vanita5.twittnuker.util.AsyncTwitterWrapper.UpdateProfileImageTask;
import de.vanita5.twittnuker.util.AsyncTwitterWrapper.UpdateProfileTask;
import de.vanita5.twittnuker.util.ImageLoaderWrapper;
import de.vanita5.twittnuker.util.ParseUtils;
import de.vanita5.twittnuker.util.TwitterWrapper;
import de.vanita5.twittnuker.util.Utils;
import de.vanita5.twittnuker.view.ProfileImageBannerLayout;
import de.vanita5.twittnuker.view.ProfileImageView;
import de.vanita5.twittnuker.view.iface.IExtendedView.OnSizeChangedListener;

import java.io.File;

public class UserProfileEditorActivity extends BaseSupportActivity implements OnSizeChangedListener, TextWatcher,
        OnClickListener, CroutonLifecycleCallback, 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 ImageLoaderWrapper mLazyImageLoader;
    private AsyncTaskManager mAsyncTaskManager;
    private AsyncTask<Void, Void, ?> mTask;

    private ProfileImageBannerLayout mProfileImageBannerLayout;
    private ProfileImageView mProfileImageView;
    private ImageView mProfileBannerView;
    private EditText mEditName, mEditDescription, mEditLocation, mEditUrl;
    private View mProgress, mContent;

    private PopupMenu mPopupMenu;

    private boolean mBackPressed;
    private long mAccountId;
    private int mBannerWidth;
    private ParcelableUser mUser;

    private boolean mUserInfoLoaderInitialized;

    private boolean mGetUserInfoCalled;

    private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(final Context context, final Intent intent) {
            final String action = intent.getAction();
            if (BROADCAST_PROFILE_UPDATED.equals(action)) {
                if (mUser == null || intent.getLongExtra(EXTRA_USER_ID, -1) == mUser.id) {
                    getUserInfo();
                }
            }
        }
    };

    private final OnMenuItemClickListener mProfileBannerImageMenuListener = new OnMenuItemClickListener() {

        @Override
        public boolean onMenuItemClick(final MenuItem item) {
            if (mUser == null)
                return false;
            switch (item.getItemId()) {
            case MENU_TAKE_PHOTO: {
                final Uri uri = createTempFileUri();
                final Intent intent = createTakePhotoIntent(uri, null, null, 2, 1, true);
                startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BANNER_IMAGE);
                mTask = new UpdateProfileBannerImageTaskInternal(UserProfileEditorActivity.this, mAsyncTaskManager,
                        mAccountId, uri, true);
                break;
            }
            case MENU_PICK_FROM_GALLERY: {
                final Uri uri = createTempFileUri();
                final Intent intent = createPickImageIntent(uri, null, null, 2, 1, true);
                try {
                    startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BANNER_IMAGE);
                    mTask = new UpdateProfileBannerImageTaskInternal(UserProfileEditorActivity.this,
                            mAsyncTaskManager, mAccountId, uri, true);
                } catch (final Exception e) {
                    if (Utils.isDebugBuild()) {
                        Log.w(LOGTAG, e);
                    }
                }
                break;
            }
            case MENU_DELETE: {
                mTask = new RemoveProfileBannerTaskInternal(mUser.account_id);
                mTask.execute();
                break;
            }
            }
            return true;
        }

    };

    private final OnMenuItemClickListener mProfileImageMenuListener = new OnMenuItemClickListener() {

        @Override
        public boolean onMenuItemClick(final MenuItem item) {
            if (mUser == null)
                return false;
            switch (item.getItemId()) {
            case MENU_TAKE_PHOTO: {
                final Uri uri = createTempFileUri();
                final Intent intent = createTakePhotoIntent(uri, null, null, 1, 1, true);
                startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
                mTask = new UpdateProfileImageTaskInternal(UserProfileEditorActivity.this, mAsyncTaskManager,
                        mAccountId, uri, true);
                break;
            }
            case MENU_PICK_FROM_GALLERY: {
                final Uri uri = createTempFileUri();
                final Intent intent = createPickImageIntent(uri, null, null, 1, 1, true);
                try {
                    startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
                    mTask = new UpdateProfileImageTaskInternal(UserProfileEditorActivity.this, mAsyncTaskManager,
                            mAccountId, uri, true);
                } catch (final Exception e) {
                    if (Utils.isDebugBuild())
                        Log.w(LOGTAG, e);
                }
                break;
            }
            }
            return true;
        }

    };

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

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

    @Override
    public void onBackPressed() {
        if (mHasUnsavedChanges() && !mBackPressed) {
            final CroutonStyle.Builder builder = new CroutonStyle.Builder(CroutonStyle.INFO);
            final Crouton crouton = Crouton.makeText(this, R.string.unsaved_change_back_pressed, builder.build());
            crouton.setLifecycleCallback(this);
            crouton.show();
            return;
        }
        super.onBackPressed();
    }

    @Override
    public void onClick(final View view) {
        if (mUser == null)
            return;
        if (mPopupMenu != null) {
            mPopupMenu.dismiss();
        }
        switch (view.getId()) {
        case ProfileImageBannerLayout.VIEW_ID_PROFILE_IMAGE: {
            mPopupMenu = PopupMenu.getInstance(this, view);
            mPopupMenu.inflate(R.menu.action_profile_image);
            mPopupMenu.setOnMenuItemClickListener(mProfileImageMenuListener);
            break;
        }
        case ProfileImageBannerLayout.VIEW_ID_PROFILE_BANNER: {
            mPopupMenu = PopupMenu.getInstance(this, view);
            mPopupMenu.inflate(R.menu.action_profile_banner_image);
            final Menu menu = mPopupMenu.getMenu();
            final MenuItem delete_submenu = menu.findItem(MENU_DELETE_SUBMENU);
            final boolean has_profile_banner = !isEmpty(mUser.profile_banner_url);
            delete_submenu.setVisible(has_profile_banner);
            delete_submenu.setEnabled(has_profile_banner);
            mPopupMenu.setOnMenuItemClickListener(mProfileBannerImageMenuListener);
            break;
        }
        default: {
            return;
        }
        }
        mPopupMenu.show();

    }

    @Override
    public void onContentChanged() {
        super.onContentChanged();
        mProgress = findViewById(R.id.progress);
        mContent = findViewById(R.id.content);
        mProfileImageBannerLayout = (ProfileImageBannerLayout) findViewById(R.id.profile_image_banner);
        mProfileBannerView = mProfileImageBannerLayout.getProfileBannerImageView();
        mProfileImageView = mProfileImageBannerLayout.getProfileImageView();
        mEditName = (EditText) findViewById(R.id.name);
        mEditDescription = (EditText) findViewById(R.id.description);
        mEditLocation = (EditText) findViewById(R.id.location);
        mEditUrl = (EditText) findViewById(R.id.url);
    }

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

    @Override
    public boolean onCreateOptionsMenu(final Menu menu, final TwidereMenuInflater inflater) {
        inflater.inflate(R.menu.menu_edit_user_profile, menu);
        return true;
    }

    @Override
    public void onDisplayed() {
        mBackPressed = true;
    }

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

    }

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

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
        case MENU_HOME: {
            onBackPressed();
            break;
        }
        case MENU_SAVE: {
            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());
            mTask = new UpdateProfileTaskInternal(this, mAsyncTaskManager, mAccountId, name, url, location,
                    description);
            mTask.execute();
            return true;
        }
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onPrepareOptionsMenu(final Menu menu) {
        final MenuItem save = menu.findItem(MENU_SAVE);
        if (save != null) {
            save.setEnabled(
                    mHasUnsavedChanges() && (mTask == null || mTask.getStatus() != AsyncTask.Status.RUNNING));
        }
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public void onRemoved() {
        mBackPressed = false;
    }

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

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

    @Override
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        if (resultCode == RESULT_CANCELED)
            return;
        if (mTask == null || mTask.getStatus() != Status.PENDING)
            return;
        switch (requestCode) {
        case REQUEST_UPLOAD_PROFILE_BANNER_IMAGE: {
            mTask.execute();
            break;
        }
        case REQUEST_UPLOAD_PROFILE_IMAGE: {
            mTask.execute();
            break;
        }
        }

    }

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        super.onCreate(savedInstanceState);
        final Intent intent = getIntent();
        final long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
        if (!isMyAccount(this, accountId)) {
            finish();
            return;
        }
        mAsyncTaskManager = TwittnukerApplication.getInstance(this).getAsyncTaskManager();
        mLazyImageLoader = TwittnukerApplication.getInstance(this).getImageLoaderWrapper();
        mAccountId = accountId;
        setContentView(R.layout.edit_user_profile);
        // setOverrideExitAniamtion(false);
        getActionBar().setDisplayHomeAsUpEnabled(true);
        mProfileImageBannerLayout.setOnSizeChangedListener(this);
        mEditName.addTextChangedListener(this);
        mEditDescription.addTextChangedListener(this);
        mEditLocation.addTextChangedListener(this);
        mEditUrl.addTextChangedListener(this);
        mProfileImageView.setOnClickListener(this);
        mProfileBannerView.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();
        final IntentFilter filter = new IntentFilter(BROADCAST_PROFILE_UPDATED);
        registerReceiver(mStatusReceiver, filter);
    }

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

    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 && user.id > 0) {
            mProgress.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;
            final int width = mBannerWidth > 0 ? mBannerWidth : def_width;
            mLazyImageLoader.displayProfileBanner(mProfileBannerView, user.profile_banner_url, width);
        } else {
            mProgress.setVisibility(View.GONE);
            mContent.setVisibility(View.GONE);
        }
    }

    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) {
        setProgressBarIndeterminateVisibility(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();
    }

    boolean mHasUnsavedChanges() {
        if (mUser == null)
            return false;
        return !stringEquals(mEditName.getText(), mUser.name)
                || !stringEquals(mEditDescription.getText(), mUser.description_expanded)
                || !stringEquals(mEditLocation.getText(), mUser.location)
                || !stringEquals(mEditUrl.getText(), isEmpty(mUser.url_expanded) ? mUser.url : mUser.url_expanded);
    }

    private static boolean stringEquals(final CharSequence str1, final CharSequence str2) {
        if (str1 == null || str2 == null)
            return str1 == str2;
        return str1.toString().equals(str2.toString());
    }

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

    }

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

        private final long account_id;

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

        @Override
        protected SingleResponse<Boolean> doInBackground(final Void... 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);
        }

    }

    class UpdateProfileTaskInternal extends UpdateProfileTask {

        public UpdateProfileTaskInternal(final Context context, final AsyncTaskManager manager,
                final long account_id, final String name, final String url, final String location,
                final String description) {
            super(context, manager, account_id, name, url, location, description);
        }

        @Override
        protected SingleResponse<ParcelableUser> doInBackground(final Void... params) {
            final SingleResponse<ParcelableUser> result = super.doInBackground(params);
            if (result.getData() != null && isMyAccount(getContext(), result.getData().id)) {
                final ContentResolver resolver = getContentResolver();
                final ContentValues values = new ContentValues();
                values.put(Accounts.NAME, result.getData().name);
                values.put(Accounts.SCREEN_NAME, result.getData().screen_name);
                values.put(Accounts.PROFILE_IMAGE_URL, result.getData().profile_image_url);
                values.put(Accounts.PROFILE_BANNER_URL, result.getData().profile_banner_url);
                final String where = Accounts.ACCOUNT_ID + " = " + result.getData().id;
                resolver.update(Accounts.CONTENT_URI, values, where, null);
            }
            return result;
        }

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

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

    }
}