info.papdt.blacklight.ui.statuses.NewPostActivity.java Source code

Java tutorial

Introduction

Here is the source code for info.papdt.blacklight.ui.statuses.NewPostActivity.java

Source

/*
 * Copyright (C) 2015 Peter Cai
 *
 * This file is part of BlackLight
 *
 * BlackLight 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.
 *
 * BlackLight 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 BlackLight.  If not, see <http://www.gnu.org/licenses/>.
 */

package info.papdt.blacklight.ui.statuses;

import android.content.SharedPreferences;
import android.support.v7.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.support.v4.widget.DrawerLayout;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import info.papdt.blacklight.R;
import info.papdt.blacklight.api.statuses.PostApi;
import info.papdt.blacklight.cache.login.LoginApiCache;
import info.papdt.blacklight.cache.user.UserApiCache;
import info.papdt.blacklight.model.UserModel;
import info.papdt.blacklight.support.AsyncTask;
import info.papdt.blacklight.support.LongPostUtility;
import info.papdt.blacklight.support.Utility;
import info.papdt.blacklight.support.Binded;
import info.papdt.blacklight.ui.comments.CommentOnActivity;
import info.papdt.blacklight.ui.comments.ReplyToActivity;
import info.papdt.blacklight.ui.common.AbsActivity;
import info.papdt.blacklight.ui.common.ColorPickerFragment;
import info.papdt.blacklight.ui.common.EmoticonFragment;
import info.papdt.blacklight.ui.common.MultiPicturePicker;

import static info.papdt.blacklight.BuildConfig.DEBUG;

public class NewPostActivity extends AbsActivity implements View.OnLongClickListener, View.OnClickListener {
    private static final String TAG = NewPostActivity.class.getSimpleName();
    private static final String DRAFT = "post_draft";
    private static final int REQUEST_PICK_IMG = 1001, REQUEST_CAPTURE_PHOTO = 1002;

    protected EditText mText;
    private TextView mCount;
    private DrawerLayout mDrawer;
    private ImageView mAvatar;
    private HorizontalScrollView mScroll;
    private LinearLayout mPicsParent;

    // Actions
    protected ImageView mPic;
    protected ImageView mEmoji;
    protected ImageView mAt;
    protected ImageView mTopic;
    protected ImageView mSend;

    // Funny hints
    private String[] mHints;

    private ImageView[] mPics = new ImageView[9];

    private LoginApiCache mLoginCache;
    private UserApiCache mUserCache;
    private UserModel mUser;

    // Fragments
    private EmoticonFragment mEmoticonFragment;
    private ColorPickerFragment mColorPickerFragment;

    // Picked picture
    private ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>();
    private ArrayList<String> mPaths = new ArrayList<String>();

    // Long?
    private boolean mIsLong = false;

    // Filter color
    private int mFilter;

    // Foreground
    private int mForeground;

    // Version
    protected String mVersion = "";

    //cache drafts
    private SharedPreferences mCache;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mLayout = R.layout.post_status;
        super.onCreate(savedInstanceState);

        mLoginCache = new LoginApiCache(this);
        mUserCache = new UserApiCache(this);
        new GetAvatarTask().execute();

        // Initialize views
        mText = Utility.findViewById(this, R.id.post_edit);
        mCount = Utility.findViewById(this, R.id.post_count);
        mDrawer = Utility.findViewById(this, R.id.post_drawer);
        mAvatar = Utility.findViewById(this, R.id.post_avatar);
        mScroll = Utility.findViewById(this, R.id.post_scroll);
        mPicsParent = Utility.findViewById(this, R.id.post_pics);
        mPic = Utility.findViewById(this, R.id.post_pic);
        mEmoji = Utility.findViewById(this, R.id.post_emoji);
        mAt = Utility.findViewById(this, R.id.post_at);
        mTopic = Utility.findViewById(this, R.id.post_topic);
        mSend = Utility.findViewById(this, R.id.post_send);
        mCache = getSharedPreferences("post_cache", MODE_PRIVATE);

        // Bind onClick events
        Utility.bindOnClick(this, mPic, "pic");
        Utility.bindOnClick(this, mEmoji, "emoji");
        Utility.bindOnClick(this, mAt, "at");
        Utility.bindOnClick(this, mTopic, "topic");
        Utility.bindOnClick(this, mSend, "send");
        Utility.bindOnClick(this, mAvatar, "avatar");

        // Version
        try {
            mVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
        } catch (Exception e) {
        }

        // Hints
        if (Math.random() < 0.42) { // Make this a matter of possibility.
            mHints = getResources().getStringArray(R.array.splashes);
            mText.setHint(mHints[new Random().nextInt(mHints.length)]);
        }

        // Fragments
        mEmoticonFragment = new EmoticonFragment();
        mColorPickerFragment = new ColorPickerFragment();
        getFragmentManager().beginTransaction().replace(R.id.post_emoticons, mEmoticonFragment).commit();

        // Filter
        try {
            TypedArray array = getTheme().obtainStyledAttributes(R.styleable.BlackLight);
            mFilter = array.getColor(R.styleable.BlackLight_NewPostImgFilter, 0);
            mForeground = array.getColor(R.styleable.BlackLight_NewPostForeground, 0);
            array.recycle();
        } catch (Exception e) {
            mFilter = 0;
        }

        // Listeners
        mEmoticonFragment.setEmoticonListener(new EmoticonFragment.EmoticonListener() {
            @Override
            public void onEmoticonSelected(String name) {
                mText.getText().insert(mText.getSelectionStart(), name);
                mDrawer.closeDrawer(Gravity.RIGHT);
            }
        });

        mColorPickerFragment.setOnColorSelectedListener(new ColorPickerFragment.OnColorSelectedListener() {
            @Override
            public void onSelected(String hex) {
                int sel = mText.getSelectionStart();
                mText.getText().insert(sel, "[" + hex + "  [d");
                mText.setSelection(sel + 9);
                mDrawer.closeDrawer(Gravity.RIGHT);
            }
        });

        mText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

                if (needCache())
                    mCache.edit().putString(DRAFT, s.toString()).apply();
            }

            @Override
            public void afterTextChanged(Editable s) {
                // How many Chinese characters (1 Chinses character = 2 English characters)
                try {
                    int length = Utility.lengthOfString(s.toString());

                    if (DEBUG) {
                        Log.d(TAG, "Text length = " + length);
                    }

                    if (length <= 140 && !s.toString().contains("\n")) {
                        mCount.setTextColor(mForeground);
                        mCount.setText(String.valueOf(140 - length));
                        mIsLong = false;
                    } else if (!(NewPostActivity.this instanceof RepostActivity)
                            && !(NewPostActivity.this instanceof CommentOnActivity)
                            && !(NewPostActivity.this instanceof ReplyToActivity)) {
                        mCount.setText(getResources().getString(R.string.long_post));
                        mIsLong = true;
                    } else {
                        mCount.setTextColor(getResources().getColor(android.R.color.holo_red_light));
                        mCount.setText(String.valueOf(140 - length));
                        mIsLong = false;
                    }

                } catch (Exception e) {

                }

                if (mEmoji != null) {
                    if (mIsLong) {
                        getFragmentManager().beginTransaction().replace(R.id.post_emoticons, mColorPickerFragment)
                                .commit();
                        mEmoji.setImageResource(R.drawable.ic_mode_edit_black_36dp);
                    } else {
                        getFragmentManager().beginTransaction().replace(R.id.post_emoticons, mEmoticonFragment)
                                .commit();
                        mEmoji.setImageResource(R.drawable.ic_emoji);

                    }
                }
            }
        });

        getWindow().getDecorView().getViewTreeObserver()
                .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        mText.requestFocus();
                        mText.requestFocusFromTouch();

                        // Draft
                        if (needCache())
                            mText.setText(mCache.getString(DRAFT, ""));

                        // Must be removed
                        getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                });

        // Imgs
        for (int i = 0; i < 9; i++) {
            mPics[i] = (ImageView) mPicsParent.getChildAt(i);
            mPics[i].setOnLongClickListener(this);
            mPics[i].setOnClickListener(this);
        }

        // Handle share intent
        Intent i = getIntent();

        if (i != null && i.getType() != null) {
            if (i.getType().contains("text/plain")) {
                mText.setText(i.getStringExtra(Intent.EXTRA_TEXT));
            } else if (i.getType().contains("image/")) {
                Uri uri = (Uri) i.getParcelableExtra(Intent.EXTRA_STREAM);

                try {
                    Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
                    addPicture(bitmap, null);
                } catch (IOException e) {
                    if (DEBUG) {
                        Log.d(TAG, Log.getStackTraceString(e));
                    }
                }
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Image picked, decode
        if (requestCode == REQUEST_PICK_IMG && resultCode == RESULT_OK) {
            if (Build.VERSION.SDK_INT >= 19) {
                try {
                    ParcelFileDescriptor parcelFileDescriptor = getContentResolver()
                            .openFileDescriptor(data.getData(), "r");
                    FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
                    Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
                    parcelFileDescriptor.close();
                    addPicture(image, null);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                Cursor cursor = getContentResolver().query(data.getData(),
                        new String[] { MediaStore.Images.Media.DATA }, null, null, null);
                cursor.moveToFirst();
                String filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                cursor.close();

                // Then decode
                addPicture(null, filePath);
            }
        } else if (requestCode == REQUEST_CAPTURE_PHOTO && resultCode == RESULT_OK) {
            addPicture(null, Utility.lastPicPath);
        } else if (resultCode == MultiPicturePicker.PICK_OK) {
            ArrayList<String> paths = data.getStringArrayListExtra("img");

            for (String path : paths) {
                addPicture(null, path);

                if (mBitmaps.size() >= 9) {
                    break;
                }
            }
        }
    }

    @Override
    public boolean onLongClick(View v) {
        for (int i = 0; i < 9; i++) {
            if (mPics[i] == v) {
                removePicture(i);
                break;
            }
        }
        return true;
    }

    @Override
    public void onClick(View v) {
        if (mIsLong) {
            // Insert pictures into long post
            for (int i = 0; i < 9; i++) {
                if (mPics[i] == v) {
                    String insert = "![" + (i + 1) + "]\n";
                    if (mText.getText().charAt(mText.getSelectionStart() - 1) != '\n') {
                        insert = "\n" + insert;
                    }
                    mText.getText().insert(mText.getSelectionStart(), insert);
                    break;
                }
            }
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.isCheckable() && item.isEnabled()) {
            item.setChecked(!item.isChecked());
        }

        int id = item.getItemId();
        if (id == android.R.id.home) {
            finish();
            return true;
        } else {
            return super.onOptionsItemSelected(item);
        }
    }

    @Binded
    public void send() {
        try {

            if (!TextUtils.isEmpty(mText.getText().toString().trim())) {
                new Uploader().execute();
            } else {
                if (mBitmaps.size() != 0 & !mIsLong) {
                    mText.setText(R.string.post_photo);
                    new Uploader().execute();
                } else {
                    Toast.makeText(this, R.string.empty_weibo, Toast.LENGTH_SHORT).show();
                }
            }
        } catch (Exception e) {

        }
    }

    @Binded
    public void pic() {
        if (mBitmaps.size() < 9) {
            showPicturePicker();
        }
    }

    @Binded
    public void emoji() {
        if (mDrawer.isDrawerOpen(Gravity.RIGHT)) {
            mDrawer.closeDrawer(Gravity.RIGHT);
        } else {
            mDrawer.openDrawer(Gravity.RIGHT);
        }
    }

    @Binded
    public void avatar() {
        mHints = getResources().getStringArray(R.array.splashes);
        mText.setHint(mHints[new Random().nextInt(mHints.length)]);
    }

    @Binded
    public void at() {
        mText.getText().insert(mText.getSelectionStart(), "@");
    }

    @Binded
    public void topic() {
        CharSequence text = mText.getText();
        mText.getText().insert(mText.getSelectionStart(), "##");
        if (text instanceof Spannable) {
            Selection.setSelection((Spannable) text, text.length() - 1);
        }
    }

    private void showPicturePicker() {
        new AlertDialog.Builder(this).setItems(getResources().getStringArray(R.array.picture_picker_array),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialogInterface, int id) {
                        switch (id) {
                        case 0:
                            Intent i = new Intent();
                            if (Build.VERSION.SDK_INT >= 19) {
                                i.setAction(Intent.ACTION_OPEN_DOCUMENT);
                                i.addCategory(Intent.CATEGORY_OPENABLE);
                                i.setType("image/*");
                            } else {
                                i.setAction(Intent.ACTION_PICK);
                                i.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                            }
                            startActivityForResult(i, REQUEST_PICK_IMG);
                            break;
                        case 1:
                            Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                            Uri uri = Utility.getOutputMediaFileUri();
                            captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                            startActivityForResult(captureIntent, REQUEST_CAPTURE_PHOTO);
                            break;
                        case 2:
                            Intent multi = new Intent();
                            multi.setAction("us.shandian.blacklight.MULTI_PICK");
                            multi.setClass(NewPostActivity.this, MultiPicturePicker.class);
                            startActivityForResult(multi, 1000);
                            break;
                        }
                    }
                }).show();
    }

    private void addPicture(Bitmap bitmap, String path) {
        if (bitmap == null) {
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(path, o);
            o.inJustDecodeBounds = false;
            o.inSampleSize = Utility.computeSampleSize(o, -1, 128 * 128);
            try {
                bitmap = BitmapFactory.decodeFile(path, o);
            } catch (OutOfMemoryError e) {
                return;
            }
        }
        mBitmaps.add(bitmap);
        mPaths.add(path);
        updatePictureView();
    }

    private void removePicture(int id) {
        mBitmaps.remove(id);
        mPaths.remove(id);
        updatePictureView();
    }

    private void updatePictureView() {
        if (mBitmaps.size() > 0) {
            mScroll.setVisibility(View.VISIBLE);
        } else {
            mScroll.setVisibility(View.GONE);
        }

        for (int i = 0; i < 9; i++) {
            Bitmap bmp = mBitmaps.size() > i ? mBitmaps.get(i) : null;
            if (bmp != null) {
                mPics[i].setVisibility(View.VISIBLE);
                mPics[i].setImageBitmap(bmp);
            } else {
                mPics[i].setVisibility(View.GONE);
                mPics[i].setImageBitmap(null);
            }
        }
    }

    // if extended, this should be overridden
    protected boolean post() {
        if (!mIsLong) {
            if (mBitmaps.size() == 0) {
                return PostApi.newPost(mText.getText().toString(), mVersion);
            } else {
                return postPics(mText.getText().toString());
            }
        } else {
            if (DEBUG) {
                Log.d(TAG, "Preparing to post a long post");
            }

            // Post the pictures with long post
            int size = mBitmaps.size();
            Bitmap[] bitmaps = new Bitmap[size];

            for (int i = 0; i < size; i++) {
                Bitmap bmp = mBitmaps.get(0);
                String path = mPaths.get(0);

                if (path != null) {
                    try {
                        bmp = BitmapFactory.decodeFile(path);
                    } catch (OutOfMemoryError e) {

                    }
                }

                mBitmaps.remove(0);
                mPaths.remove(0);

                bitmaps[i] = bmp;
            }

            Bitmap bmp = LongPostUtility.parseLongPost(this, mText.getText().toString(), bitmaps);
            mBitmaps.add(0, bmp);
            mPaths.add(0, null);

            return postPics(LongPostUtility.parseLongContent(this, mText.getText().toString()));
        }
    }

    private boolean postPics(String status) {
        // Upload pictures first
        String pics = "";

        for (int i = 0; i < mBitmaps.size(); i++) {
            Bitmap bmp = mBitmaps.get(i);
            String path = mPaths.get(i);
            if (path != null) {
                try {
                    bmp = BitmapFactory.decodeFile(path);
                } catch (OutOfMemoryError e) {
                    continue;
                }
            }
            String id = PostApi.uploadPicture(bmp);
            if (id == null || id.trim().equals(""))
                return false;

            pics += id;

            if (i < mBitmaps.size() - 1) {
                pics += ",";
            }
        }

        // Upload text
        return PostApi.newPostWithMultiPics(status, pics, mVersion);
    }

    //for draft
    protected boolean needCache() {
        return true;
    }

    private class Uploader extends AsyncTask<Void, Void, Boolean> {
        private ProgressDialog prog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            prog = new ProgressDialog(NewPostActivity.this);
            prog.setMessage(getResources().getString(R.string.plz_wait));
            prog.setCancelable(false);
            prog.show();
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            return post();
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);

            prog.dismiss();

            if (result) {
                if (needCache())
                    mCache.edit().putString(DRAFT, "").apply();
                finish();
            } else {
                new AlertDialog.Builder(NewPostActivity.this).setMessage(R.string.send_fail).setCancelable(true)
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int index) {
                                dialog.dismiss();
                            }
                        }).create().show();
            }
        }

    }

    private class GetAvatarTask extends AsyncTask<Void, Object, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            // User first
            mUser = mUserCache.getUser(mLoginCache.getUid());

            // Avatar
            Bitmap avatar = mUserCache.getLargeAvatar(mUser);
            if (avatar != null)
                publishProgress(1, avatar);

            return null;
        }

        @Override
        protected void onProgressUpdate(Object... values) {
            switch (Integer.valueOf(values[0].toString())) {
            case 1:
                mAvatar.setImageBitmap((Bitmap) values[1]);
                break;
            }
            super.onProgressUpdate();
        }

    }
}