com.near.chimerarevo.fragments.CommentsFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.near.chimerarevo.fragments.CommentsFragment.java

Source

/*
* Copyright (C) 2013-2015 Simone Renzo.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.near.chimerarevo.fragments;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.melnykov.fab.FloatingActionButton;
import com.near.chimerarevo.R;
import com.near.chimerarevo.adapters.CommentsAdapter;
import com.near.chimerarevo.misc.Constants;
import com.near.chimerarevo.utils.JSONUtils;
import com.near.chimerarevo.utils.OkHttpUtils;
import com.near.chimerarevo.utils.ProgressDialogUtils;
import com.near.chimerarevo.utils.SnackbarUtils;
import com.near.chimerarevo.utils.URLUtils;
import com.nispok.snackbar.Snackbar;
import com.nispok.snackbar.listeners.EventListener;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.http.SslError;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.AnimationUtils;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

import uk.me.lewisdeane.ldialogs.BaseDialog;
import uk.me.lewisdeane.ldialogs.CustomDialog;

public class CommentsFragment extends ListFragment implements OnClickListener, EventListener {

    private static final String FRAGMENT_TAG = "CommentsFragment";

    private final Object attachingActivityLock = new Object();
    private boolean syncVariable = false;

    private Handler mHandler = new Handler();

    private ProgressDialog mDialog;

    private CommentsAdapter mAdapter;

    private ArrayList<HashMap<String, String>> arrayList;

    private FloatingActionButton mFab;
    private TextView mEmptyText;
    private View mProgressContainer;
    private View mListContainer;

    private String thread_id, access_token;
    private int parentId = -1;
    private boolean isDialogOpen = false;
    private boolean mListShown = false;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        synchronized (attachingActivityLock) {
            syncVariable = true;
            attachingActivityLock.notifyAll();
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.comment_list_layout, container, false);

        if (getArguments().containsKey("isLandscapeLarge") && !getArguments().getBoolean("isLandscapeLarge"))
            v.setPadding(0, getResources().getDimensionPixelSize(R.dimen.actionbar_height), 0, 0);

        mFab = (FloatingActionButton) v.findViewById(R.id.floating_action);
        mProgressContainer = v.findViewById(R.id.progressContainer);
        mListContainer = v.findViewById(R.id.listContainer);

        mEmptyText = (TextView) v.findViewById(android.R.id.empty);
        mEmptyText.setText(R.string.text_nocomments);

        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        arrayList = new ArrayList<>();
        mAdapter = new CommentsAdapter(arrayList);
        setListAdapter(mAdapter);

        mFab.attachToListView(getListView());
        mFab.setOnClickListener(this);

        if (getArguments().containsKey(Constants.KEY_URL))
            performUpdate();
        else {
            setListShown(true);
            mFab.setVisibility(View.GONE);
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        parentId = mAdapter.getCommentId(position);
        if (access_token == null)
            loadDisqusOAuth();
        else
            createCommentDialog(parentId);
    }

    @Override
    public void onClick(View view) {
        if (!isDialogOpen) {
            mFab.hide();
            parentId = -1;
            if (access_token == null)
                loadDisqusOAuth();
            else
                createCommentDialog(parentId);
        }
    }

    @Override
    public void onShow(Snackbar snackbar) {
        if (mFab != null)
            mFab.hide();
    }

    @Override
    public void onShowByReplace(Snackbar snackbar) {
        // do nothing
    }

    @Override
    public void onShown(Snackbar snackbar) {
        // do nothing
    }

    @Override
    public void onDismiss(Snackbar snackbar) {
        // do nothing
    }

    @Override
    public void onDismissByReplace(Snackbar snackbar) {
        // do nothing
    }

    @Override
    public void onDismissed(Snackbar snackbar) {
        if (mFab != null)
            mFab.show();
    }

    public void setListShown(boolean shown, boolean animate) {
        if (mListShown == shown)
            return;

        mListShown = shown;
        if (shown) {
            if (animate) {
                try {
                    mProgressContainer
                            .startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out));
                    mListContainer
                            .startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            mProgressContainer.setVisibility(View.GONE);
            mListContainer.setVisibility(View.VISIBLE);
        } else {
            if (animate) {
                try {
                    mProgressContainer
                            .startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
                    mListContainer
                            .startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            mProgressContainer.setVisibility(View.VISIBLE);
            mListContainer.setVisibility(View.INVISIBLE);
        }
    }

    public void setListShown(boolean shown) {
        setListShown(shown, true);
    }

    public void performUpdate() {
        arrayList.clear();

        synchronized (attachingActivityLock) {
            while (!syncVariable) {
                try {
                    attachingActivityLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        Request request = new Request.Builder()
                .url(URLUtils.getThreadIdUrl(getArguments().getString(Constants.KEY_URL))).tag(FRAGMENT_TAG)
                .build();
        OkHttpUtils.getInstance().newCall(request).enqueue(new ThreadIdCallback());
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void loadDisqusOAuth() {
        if (getActivity().getSharedPreferences(Constants.PREFS_TAG, Context.MODE_PRIVATE)
                .getString(Constants.KEY_REFRESH_TOKEN, "").length() > 1) {

            RequestBody formBody = new FormEncodingBuilder().add("grant_type", "refresh_token")
                    .add("client_id", Constants.DISQUS_API_KEY).add("client_secret", Constants.DISQUS_API_SECRET)
                    .add("refresh_token",
                            getActivity().getSharedPreferences(Constants.PREFS_TAG, Context.MODE_PRIVATE)
                                    .getString(Constants.KEY_REFRESH_TOKEN, ""))
                    .build();

            Request request = new Request.Builder().url(Constants.DISQUS_TOKEN_URL).post(formBody).tag(FRAGMENT_TAG)
                    .build();

            if (mDialog == null)
                mDialog = ProgressDialogUtils.getInstance(getActivity(), R.string.text_login);
            else
                mDialog = ProgressDialogUtils.modifyInstance(mDialog, R.string.text_login);

            mDialog.show();
            OkHttpUtils.getInstance().newCall(request).enqueue(new PostAccessTokenCallback());

            return;
        }

        final Dialog dialog = new Dialog(getActivity());

        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(R.layout.webview_layout);
        dialog.setCancelable(true);

        dialog.setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface arg0) {
                isDialogOpen = false;
                mFab.show();
            }
        });
        dialog.setOnDismissListener(new OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface arg0) {
                isDialogOpen = false;
                mFab.show();
            }
        });

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
            CookieManager.getInstance().removeAllCookies(null);
        else {
            CookieSyncManager.createInstance(getActivity());
            CookieManager.getInstance().removeAllCookie();
        }

        WebView wv = (WebView) dialog.findViewById(R.id.webview);
        wv.getSettings().setJavaScriptEnabled(true);
        wv.getSettings().setSaveFormData(false);
        wv.setWebViewClient(new WebViewClient() {

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                dialog.findViewById(R.id.progressContainer).setVisibility(View.GONE);
                dialog.findViewById(R.id.webViewContainer).setVisibility(View.VISIBLE);
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                dialog.findViewById(R.id.progressContainer).setVisibility(View.VISIBLE);
                dialog.findViewById(R.id.webViewContainer).setVisibility(View.GONE);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                boolean state = super.shouldOverrideUrlLoading(view, url);
                if (url.contains(Constants.SITE_URL)) {
                    String code = url.split("code=")[1];

                    RequestBody formBody = new FormEncodingBuilder().add("grant_type", "authorization_code")
                            .add("client_id", Constants.DISQUS_API_KEY)
                            .add("client_secret", Constants.DISQUS_API_SECRET)
                            .add("redirect_uri", Constants.SITE_URL).add("code", code).build();

                    Request request = new Request.Builder().url(Constants.DISQUS_TOKEN_URL).post(formBody)
                            .tag(FRAGMENT_TAG).build();

                    if (mDialog == null)
                        mDialog = ProgressDialogUtils.getInstance(getActivity(), R.string.text_login);
                    else
                        mDialog = ProgressDialogUtils.modifyInstance(mDialog, R.string.text_login);

                    dialog.dismiss();
                    mDialog.show();

                    OkHttpUtils.getInstance().newCall(request).enqueue(new PostAccessTokenCallback());
                }
                return state;
            }

            @Override
            public void onReceivedSslError(WebView view, @NonNull SslErrorHandler handler, SslError error) {
                handler.proceed();
            }

        });
        wv.loadUrl(URLUtils.getDisqusAuthUrl());

        isDialogOpen = true;
        mFab.hide();
        dialog.show();
    }

    private void createCommentDialog(final int parent) {
        CustomDialog.Builder builder;

        if (parentId == -1)
            builder = new CustomDialog.Builder(getActivity(), getResources().getString(R.string.text_addcomment),
                    getResources().getString(R.string.text_sendcomment));
        else
            builder = new CustomDialog.Builder(getActivity(), getResources().getString(R.string.text_replycomment),
                    getResources().getString(R.string.text_sendcomment));

        builder.positiveColorRes(android.R.color.holo_blue_bright);
        builder.titleColorRes(android.R.color.holo_red_light);
        builder.titleAlignment(BaseDialog.Alignment.CENTER);
        builder.negativeText(getResources().getString(R.string.text_cancel));
        builder.negativeColorRes(android.R.color.holo_red_dark);

        final CustomDialog dialog = builder.build();
        dialog.setCustomView(
                LayoutInflater.from(getActivity()).inflate(R.layout.dialog_comment_layout, null, false));
        dialog.setCancelable(false);

        dialog.setClickListener(new CustomDialog.ClickListener() {
            @Override
            public void onConfirmClick() {
                EditText text = (EditText) dialog.findViewById(R.id.comment_edittext);

                isDialogOpen = false;

                if (checkEditText(text, getResources())) {
                    SnackbarUtils
                            .showMultiShortSnackbar(getActivity(),
                                    getResources().getString(R.string.text_textnotempty), CommentsFragment.this)
                            .dismissOnActionClicked(true).actionLabel(getResources().getString(R.string.text_close))
                            .actionColor(getResources().getColor(android.R.color.holo_red_dark))
                            .show(getActivity());

                    return;
                }

                String commentText = text.getText().toString() + "\n\n"
                        + getResources().getString(R.string.text_sentfromapp);

                FormEncodingBuilder feb = new FormEncodingBuilder().add("access_token", access_token)
                        .add("api_key", Constants.DISQUS_API_KEY).add("api_secret", Constants.DISQUS_API_SECRET)
                        .add("message", commentText).add("thread", thread_id);

                if (parent != -1)
                    feb.add("parent", String.valueOf(parent));

                Request request = new Request.Builder().url(Constants.DISQUS_POST_COMMENT).post(feb.build())
                        .tag(FRAGMENT_TAG).build();

                if (mDialog == null)
                    mDialog = ProgressDialogUtils.getInstance(getActivity(), R.string.text_sending_comment);
                else
                    mDialog = ProgressDialogUtils.modifyInstance(mDialog, R.string.text_sending_comment);

                mDialog.show();

                OkHttpUtils.getInstance().newCall(request).enqueue(new PostCommentCallback());
            }

            @Override
            public void onCancelClick() {
                isDialogOpen = false;
                mFab.show();
            }
        });

        isDialogOpen = true;
        mFab.hide();
        dialog.show();
    }

    private static boolean checkEditText(EditText ed, Resources res) {
        if (ed.getText().toString().trim().equals("")) {
            ed.setError(res.getString(R.string.error_field_required));
            ed.requestFocus();
            return true;
        } else {
            ed.setError(null);
            return false;
        }
    }

    private void setItems(JSONArray jArray) {
        for (int i = 0; i < jArray.length(); i++) {
            try {
                final JSONObject jObject = jArray.getJSONObject(i);
                addItem(jObject);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        mAdapter.notifyDataSetChanged();
    }

    private void addItem(final JSONObject jObject) throws JSONException {
        HashMap<String, String> map = new HashMap<>();
        map.put(Constants.KEY_ID, jObject.getString(Constants.KEY_ID));
        map.put(Constants.KEY_NAME, jObject.getJSONObject(Constants.KEY_AUTHOR).getString(Constants.KEY_NAME));
        map.put(Constants.KEY_DATE, jObject.getString(Constants.KEY_CREATEDAT).replaceAll("T", " "));
        map.put(Constants.KEY_MESSAGE, jObject.getString(Constants.KEY_MESSAGE));
        map.put(Constants.KEY_IMG, jObject.getJSONObject(Constants.KEY_AUTHOR).getJSONObject(Constants.KEY_AVATAR)
                .getString(Constants.KEY_URL));
        arrayList.add(map);
    }

    private class ThreadIdCallback implements Callback {

        @Override
        public void onFailure(Request request, final IOException e) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    SnackbarUtils.showShortSnackbar(getActivity(), e.getMessage(), CommentsFragment.this)
                            .show(getActivity());
                }
            });
        }

        @Override
        public void onResponse(final Response response) throws IOException {
            if (response.code() == 200)
                new CheckThreadIdTask().execute(response.body().string());
            else
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        SnackbarUtils.showShortSnackbar(getActivity(), response.message(), CommentsFragment.this)
                                .show(getActivity());
                    }
                });
        }
    }

    private class CheckThreadIdTask extends AsyncTask<String, Void, Void> {

        @Override
        protected Void doInBackground(String... params) {

            if (!isOnline())
                return null;

            try {
                JSONArray jArray = JSONUtils.getJSONArray(params[0], Constants.KEY_RESPONSE);

                for (int i = 0; i < jArray.length(); i++) {
                    JSONObject obj = jArray.getJSONObject(i);

                    try {
                        URL curUrl = new URL(obj.getString(Constants.DISQUS_LINK_TAG));
                        HttpURLConnection ucon = (HttpURLConnection) curUrl.openConnection();
                        ucon.setInstanceFollowRedirects(true);
                        String secondUrl = ucon.getHeaderField("Location");

                        if (secondUrl == null)
                            secondUrl = obj.getString(Constants.DISQUS_LINK_TAG);

                        if (secondUrl.equals(getArguments().getString(Constants.KEY_URL))) {
                            thread_id = obj.getString(Constants.KEY_ID);
                        }
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }

                }

            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            if (thread_id == null) {
                mEmptyText.setText(R.string.error_disqus);
                mFab.setVisibility(View.GONE);
                setListShown(true);
            } else {
                Request request = new Request.Builder().url(URLUtils.getCommentsUrl(thread_id)).tag(FRAGMENT_TAG)
                        .build();
                OkHttpUtils.getInstance().newCall(request).enqueue(new GetCommentsCallback());
            }
        }

        public boolean isOnline() {
            try {
                ConnectivityManager cm = (ConnectivityManager) getActivity()
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                return netInfo != null && netInfo.isConnectedOrConnecting();
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

    }

    private class PostAccessTokenCallback implements Callback {

        @Override
        public void onFailure(Request request, final IOException e) {
            if (mDialog.isShowing())
                mDialog.dismiss();

            getActivity().getSharedPreferences(Constants.PREFS_TAG, Context.MODE_PRIVATE).edit()
                    .remove(Constants.KEY_REFRESH_TOKEN).commit();

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    SnackbarUtils.showShortSnackbar(getActivity(), e.getMessage(), CommentsFragment.this)
                            .show(getActivity());
                    loadDisqusOAuth();
                }
            });
        }

        @Override
        public void onResponse(final Response response) throws IOException {
            if (mDialog.isShowing())
                mDialog.dismiss();

            if (response.code() != 200) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        SnackbarUtils.showShortSnackbar(getActivity(), response.message(), CommentsFragment.this)
                                .show(getActivity());
                    }
                });

                return;
            }

            try {
                JSONObject jObject = new JSONObject(response.body().string());
                access_token = jObject.getString(Constants.KEY_ACCESS_TOKEN);
                getActivity().getSharedPreferences(Constants.PREFS_TAG, Context.MODE_PRIVATE).edit()
                        .putString(Constants.KEY_REFRESH_TOKEN, jObject.getString(Constants.KEY_REFRESH_TOKEN))
                        .apply();

                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        createCommentDialog(parentId);
                    }
                });
            } catch (JSONException e) {
                e.printStackTrace();
                getActivity().getSharedPreferences(Constants.PREFS_TAG, Context.MODE_PRIVATE).edit()
                        .remove(Constants.KEY_REFRESH_TOKEN).apply();

                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        loadDisqusOAuth();
                    }
                });
            }
        }
    }

    private class GetCommentsCallback implements Callback {

        @Override
        public void onFailure(Request request, final IOException e) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    SnackbarUtils.showShortSnackbar(getActivity(), e.getMessage(), CommentsFragment.this)
                            .show(getActivity());
                }
            });
        }

        @Override
        public void onResponse(final Response response) throws IOException {
            if (response.code() != 200) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        SnackbarUtils.showShortSnackbar(getActivity(), response.message(), CommentsFragment.this)
                                .show(getActivity());
                    }
                });

                return;
            }

            final String body = response.body().string();

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        setItems(JSONUtils.getJSONArray(body, Constants.KEY_RESPONSE));
                        setListShown(true);
                    } catch (Exception e) {
                        e.printStackTrace();
                        setListShown(true);
                    }
                }
            });
        }
    }

    private class PostCommentCallback implements Callback {

        @Override
        public void onFailure(Request request, final IOException e) {
            if (mDialog.isShowing())
                mDialog.dismiss();

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    SnackbarUtils.showShortSnackbar(getActivity(), e.getMessage(), CommentsFragment.this)
                            .show(getActivity());
                }
            });
        }

        @Override
        public void onResponse(Response response) throws IOException {
            if (mDialog.isShowing())
                mDialog.dismiss();

            if (response == null || !response.isSuccessful()) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        SnackbarUtils.showShortSnackbar(getActivity(),
                                getResources().getString(R.string.error_occurred), CommentsFragment.this)
                                .show(getActivity());
                    }
                });
            } else {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        SnackbarUtils
                                .showShortSnackbar(getActivity(),
                                        getResources().getString(R.string.text_commentsent), CommentsFragment.this)
                                .show(getActivity());
                    }
                });

                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        performUpdate();
                    }
                }, 4000);
            }
        }
    }

}