com.irccloud.android.activity.PastebinsActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.irccloud.android.activity.PastebinsActivity.java

Source

/*
 * Copyright (c) 2015 IRCCloud, Ltd.
 *
 * 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.irccloud.android.activity;

import android.app.ActivityManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.crashlytics.android.Crashlytics;
import com.damnhandy.uri.template.UriTemplate;
import com.irccloud.android.AsyncTaskEx;
import com.irccloud.android.ColorFormatter;
import com.irccloud.android.IRCCloudJSONObject;
import com.irccloud.android.NetworkConnection;
import com.irccloud.android.R;

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

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

public class PastebinsActivity extends BaseActivity {
    private int page = 0;
    private int reqid = -1;
    private PastebinsAdapter adapter = new PastebinsAdapter();
    private boolean canLoadMore = true;
    private View footer;
    private Pastebin pasteToDelete;

    private static class Pastebin implements Serializable {
        private static final long serialVersionUID = 0L;

        String id;
        String name;
        String url;
        int lines;
        Date date;
        String date_formatted;
        String body;
        String extension;
        boolean own_paste;
    }

    private class PastebinsAdapter extends BaseAdapter {
        private class ViewHolder {
            TextView name;
            TextView date;
            TextView body;
            ImageButton delete;
        }

        private ArrayList<Pastebin> pastebins = new ArrayList<>();
        private HashMap<String, String> extensions = new HashMap<>();
        private HashMap<String, String> fileTypes = new HashMap<String, String>() {
            {
                put("ABAP", "abap");
                put("ActionScript", "as");
                put("ADA", "ada|adb");
                put("Apache Conf", "^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd");
                put("AsciiDoc", "asciidoc");
                put("Assembly_x86", "asm");
                put("AutoHotKey", "ahk");
                put("BatchFile", "bat|cmd");
                put("C9Search", "c9search_results");
                put("C/C++", "cpp|c|cc|cxx|h|hh|hpp");
                put("Cirru", "cirru|cr");
                put("Clojure", "clj|cljs");
                put("Cobol", "cbl|cob");
                put("CoffeeScript", "coffee|cf|cson|^cakefile");
                put("ColdFusion", "cfm");
                put("C#", "cs");
                put("CSS", "css");
                put("Curly", "curly");
                put("D", "d|di");
                put("Dart", "dart");
                put("Diff", "diff|patch");
                put("Dockerfile", "^dockerfile");
                put("Dot", "dot");
                put("Erlang", "erl|hrl");
                put("EJS", "ejs");
                put("Forth", "frt|fs|ldr");
                put("FreeMarker", "ftl");
                put("Gherkin", "feature");
                put("Gitignore", "^.gitignore");
                put("Glsl", "glsl|frag|vert");
                put("Go", "go");
                put("Groovy", "groovy");
                put("HAML", "haml");
                put("Handlebars", "hbs|handlebars|tpl|mustache");
                put("Haskell", "hs");
                put("haXe", "hx");
                put("HTML", "html|htm|xhtml");
                put("HTML (Ruby)", "erb|rhtml|html.erb");
                put("INI", "ini|conf|cfg|prefs");
                put("Jack", "jack");
                put("Jade", "jade");
                put("Java", "java");
                put("JavaScript", "js|jsm");
                put("JSON", "json");
                put("JSONiq", "jq");
                put("JSP", "jsp");
                put("JSX", "jsx");
                put("Julia", "jl");
                put("LaTeX", "tex|latex|ltx|bib");
                put("LESS", "less");
                put("Liquid", "liquid");
                put("Lisp", "lisp");
                put("LiveScript", "ls");
                put("LogiQL", "logic|lql");
                put("LSL", "lsl");
                put("Lua", "lua");
                put("LuaPage", "lp");
                put("Lucene", "lucene");
                put("Makefile", "makefile|gnumakefile|ocamlmakefile|make");
                put("MATLAB", "matlab");
                put("Markdown", "md|markdown");
                put("MEL", "mel");
                put("MySQL", "mysql");
                put("MUSHCode", "mc|mush");
                put("Nix", "nix");
                put("Objective-C", "m|mm");
                put("OCaml", "ml|mli");
                put("Pascal", "pas|p");
                put("Perl", "pl|pm");
                put("pgSQL", "pgsql");
                put("PHP", "php|phtml");
                put("Powershell", "ps1");
                put("Prolog", "plg|prolog");
                put("Properties", "properties");
                put("Protobuf", "proto");
                put("Python", "py");
                put("R", "r");
                put("RDoc", "rd");
                put("RHTML", "rhtml");
                put("Ruby", "rb|ru|gemspec|rake|^guardfile|^rakefile|^gemfile");
                put("Rust", "rs");
                put("SASS", "sass");
                put("SCAD", "scad");
                put("Scala", "scala");
                put("Smarty", "smarty|tpl");
                put("Scheme", "scm|rkt");
                put("SCSS", "scss");
                put("SH", "sh|bash|bashrc");
                put("SJS", "sjs");
                put("Space", "space");
                put("snippets", "snippets");
                put("Soy Template", "soy");
                put("SQL", "sql");
                put("Stylus", "styl|stylus");
                put("SVG", "svg");
                put("Tcl", "tcl");
                put("Tex", "tex");
                put("Text", "txt");
                put("Textile", "textile");
                put("Toml", "toml");
                put("Twig", "twig");
                put("Typescript", "ts|typescript|str");
                put("Vala", "vala");
                put("VBScript", "vbs");
                put("Velocity", "vm");
                put("Verilog", "v|vh|sv|svh");
                put("XML", "xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl");
                put("XQuery", "xq");
                put("YAML", "yaml|yml");
            }
        };

        public void clear() {
            pastebins.clear();
            notifyDataSetInvalidated();
        }

        public void saveInstanceState(Bundle state) {
            state.putSerializable("adapter", pastebins.toArray(new Pastebin[pastebins.size()]));
        }

        public void addPastebin(String id, String name, int lines, Date date, String body, String extension,
                boolean own_paste) {
            Pastebin p = new Pastebin();
            p.id = id;
            p.name = name;
            p.lines = lines;
            p.date = date;
            p.body = body;
            p.extension = extension;
            p.own_paste = own_paste;
            p.url = UriTemplate.fromTemplate(ColorFormatter.pastebin_uri_template).set("id", p.id)
                    .set("name", p.name).expand();

            addPastebin(p);
        }

        public void addPastebin(Pastebin p) {
            pastebins.add(p);
        }

        @Override
        public int getCount() {
            return pastebins.size();
        }

        @Override
        public Object getItem(int i) {
            return pastebins.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        private View.OnClickListener deleteClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pasteToDelete = (Pastebin) getItem((Integer) view.getTag());
                AlertDialog.Builder builder = new AlertDialog.Builder(PastebinsActivity.this);
                builder.setTitle("Delete Pastebin");
                if (pasteToDelete.name != null && pasteToDelete.name.length() > 0) {
                    builder.setMessage("Are you sure you want to delete '" + pasteToDelete.name + "'?");
                } else {
                    builder.setMessage("Are you sure you want to delete this pastebin?");
                }
                builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        reqid = NetworkConnection.getInstance().delete_paste(pasteToDelete.id);
                        pastebins.remove(pasteToDelete);
                        notifyDataSetChanged();
                    }
                });
                builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.dismiss();
                        pasteToDelete = null;
                    }
                });
                AlertDialog d = builder.create();
                d.setOwnerActivity(PastebinsActivity.this);
                d.show();
            }
        };

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            View row = view;
            ViewHolder holder;

            if (row == null) {
                LayoutInflater inflater = getLayoutInflater();
                row = inflater.inflate(R.layout.row_pastebin, viewGroup, false);

                holder = new ViewHolder();
                holder.name = (TextView) row.findViewById(R.id.name);
                holder.date = (TextView) row.findViewById(R.id.date);
                holder.body = (TextView) row.findViewById(R.id.body);
                holder.delete = (ImageButton) row.findViewById(R.id.delete);

                row.setTag(holder);
            } else {
                holder = (ViewHolder) row.getTag();
            }

            try {
                Pastebin p = pastebins.get(i);
                if (p.date_formatted == null) {
                    p.date_formatted = DateUtils.getRelativeTimeSpanString(p.date.getTime(),
                            System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS, 0).toString();
                    p.date_formatted += "  " + p.lines + " line";
                    if (p.lines != 1)
                        p.date_formatted += "s";

                    String extension = "Text";
                    if (p.extension != null && p.extension.length() > 0) {
                        if (extensions.containsKey(p.extension.toLowerCase())) {
                            extension = extensions.get(p.extension.toLowerCase());
                        } else {
                            String lower = p.extension.toLowerCase();
                            for (String type : fileTypes.keySet()) {
                                if (lower.matches(fileTypes.get(type))) {
                                    extension = type;
                                }
                            }
                            extensions.put(lower, extension);
                        }
                    }
                    p.date_formatted += "  " + extension;
                }
                holder.date.setText(p.date_formatted);
                holder.body.setText(p.body);
                if (p.name != null && p.name.length() > 0) {
                    holder.name.setText(p.name);
                    holder.name.setVisibility(View.VISIBLE);
                } else {
                    holder.name.setVisibility(View.GONE);
                }
                holder.delete.setOnClickListener(deleteClickListener);
                holder.delete.setTag(i);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return row;
        }
    }

    private class FetchPastebinsTask extends AsyncTaskEx<Void, Void, JSONObject> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            canLoadMore = false;
        }

        @Override
        protected JSONObject doInBackground(Void... params) {
            try {
                Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
                return NetworkConnection.getInstance().pastebins(++page);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        protected void onPostExecute(JSONObject jsonObject) {
            if (jsonObject != null) {
                try {
                    if (jsonObject.getBoolean("success")) {
                        JSONArray pastebins = jsonObject.getJSONArray("pastebins");
                        Log.e("IRCCloud", "Got " + pastebins.length() + " pastebins for page " + page);
                        for (int i = 0; i < pastebins.length(); i++) {
                            JSONObject pastebin = pastebins.getJSONObject(i);
                            adapter.addPastebin(pastebin.getString("id"), pastebin.getString("name"),
                                    pastebin.getInt("lines"), new Date(pastebin.getLong("date") * 1000L),
                                    pastebin.getString("body"), pastebin.getString("extension"),
                                    pastebin.getBoolean("own_paste"));
                        }
                        adapter.notifyDataSetChanged();
                        canLoadMore = pastebins.length() > 0 && adapter.getCount() < jsonObject.getInt("total");
                        if (!canLoadMore)
                            footer.findViewById(R.id.progress).setVisibility(View.GONE);
                    } else {
                        page--;
                        Log.e("IRCCloud", "Failed: " + jsonObject.toString());
                        if (jsonObject.has("message") && jsonObject.getString("message").equals("server_error")) {
                            canLoadMore = true;
                            new FetchPastebinsTask().execute((Void) null);
                        } else {
                            canLoadMore = false;
                        }
                    }
                } catch (JSONException e) {
                    page--;
                    e.printStackTrace();
                }
            } else {
                page--;
                canLoadMore = true;
                new FetchPastebinsTask().execute((Void) null);
            }
            checkEmpty();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT >= 21) {
            Bitmap cloud = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
            setTaskDescription(new ActivityManager.TaskDescription(getResources().getString(R.string.app_name),
                    cloud, 0xFFF2F7FC));
            cloud.recycle();
        }

        setContentView(R.layout.ignorelist);

        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setHomeAsUpIndicator(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
            getSupportActionBar().setBackgroundDrawable(getResources().getDrawable(R.drawable.actionbar));
            getSupportActionBar().setElevation(0);
        }

        if (savedInstanceState != null && savedInstanceState.containsKey("adapter")) {
            try {
                page = savedInstanceState.getInt("page");
                Pastebin[] pastebins = (Pastebin[]) savedInstanceState.getSerializable("adapter");
                for (Pastebin p : pastebins) {
                    adapter.addPastebin(p);
                }
                adapter.notifyDataSetChanged();
            } catch (Exception e) {
                page = 0;
                adapter.clear();
            }
        }

        footer = getLayoutInflater().inflate(R.layout.messageview_header, null);
        ListView listView = (ListView) findViewById(android.R.id.list);
        listView.setAdapter(adapter);
        listView.addFooterView(footer);
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int i) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (canLoadMore && firstVisibleItem + visibleItemCount > totalItemCount - 4) {
                    canLoadMore = false;
                    new FetchPastebinsTask().execute((Void) null);
                }
            }
        });
        listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {

            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                final Pastebin p = (Pastebin) adapter.getItem(i);

                Intent intent = new Intent(PastebinsActivity.this, PastebinViewerActivity.class);
                intent.setData(Uri.parse(p.url + "?id=" + p.id + "&own_paste=" + (p.own_paste ? "1" : "0")));
                startActivity(intent);
            }
        });

        Toast.makeText(this, "Tap a pastebin to view full text with syntax highlighting", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onResume() {
        super.onResume();
        NetworkConnection.getInstance().addHandler(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        NetworkConnection.getInstance().removeHandler(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (adapter != null)
            adapter.clear();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt("page", page);
        adapter.saveInstanceState(outState);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return false;
    }

    public void onIRCEvent(int what, Object o) {
        IRCCloudJSONObject obj;
        switch (what) {
        case NetworkConnection.EVENT_SUCCESS:
            obj = (IRCCloudJSONObject) o;
            if (obj.getInt("_reqid") == reqid) {
                Log.d("IRCCloud", "Pastebin deleted successfully");
                reqid = -1;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        adapter.pastebins.remove(pasteToDelete);
                        adapter.notifyDataSetChanged();
                        checkEmpty();
                        pasteToDelete = null;
                    }
                });
            }
            break;
        case NetworkConnection.EVENT_FAILURE_MSG:
            obj = (IRCCloudJSONObject) o;
            if (reqid != -1 && obj.getInt("_reqid") == reqid) {
                Crashlytics.log(Log.ERROR, "IRCCloud", "Delete failed: " + obj.toString());
                reqid = -1;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        AlertDialog.Builder builder = new AlertDialog.Builder(PastebinsActivity.this);
                        builder.setTitle("Error");
                        builder.setMessage("Unable to delete this pastebin.  Please try again shortly.");
                        builder.setPositiveButton("Close", null);
                        builder.show();
                    }
                });
            }
            break;
        default:
            break;
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void checkEmpty() {
        if (adapter.getCount() == 0 && !canLoadMore) {
            findViewById(android.R.id.list).setVisibility(View.GONE);
            TextView empty = (TextView) findViewById(android.R.id.empty);
            empty.setVisibility(View.VISIBLE);
            empty.setText("You haven't created any pastebins yet.");
        } else {
            findViewById(android.R.id.list).setVisibility(View.VISIBLE);
            findViewById(android.R.id.empty).setVisibility(View.GONE);
        }
    }
}