com.juick.android.ThreadActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.juick.android.ThreadActivity.java

Source

/*
 * Juick
 * Copyright (C) 2008-2012, Ugnich Anton
 *
 * 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 com.juick.android;

import android.app.ActionBar;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v4.app.FragmentTransaction;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.StyleSpan;
import android.view.*;
import android.view.Window;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.*;
import com.actionbarsherlock.view.Menu;
import com.crashlytics.android.Crashlytics;
import com.juick.android.facebook.FacebookFeedMessagesSource;
import com.juickadvanced.data.juick.JuickMessage;
import com.juickadvanced.data.juick.JuickUser;
import com.juickadvanced.data.MessageID;
import com.juick.android.juick.MessagesSource;
import com.juickadvanced.R;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;

/**
 *
 * @author Ugnich Anton
 */
public class ThreadActivity extends JuickFragmentActivity
        implements View.OnClickListener, DialogInterface.OnClickListener, ThreadFragment.ThreadFragmentListener {

    public static int instanceCount = 0;

    public static final int ACTIVITY_ATTACHMENT_IMAGE = 2;
    public static final int ACTIVITY_ATTACHMENT_VIDEO = 3;
    private TextView tvReplyTo;
    private RelativeLayout replyToContainer;
    private Button showThread;
    private Button draftsButton;
    private boolean enableDrafts;
    EditText etMessage;
    private String pulledDraft; // originally pulled draft text, saved to compare and ignore save question
    private String pulledDraftMid;
    private long pulledDraftRid;
    private long pulledDraftTs;
    public ImageButton bSend;
    private ImageButton bAttach;
    private MessageID mid = null;
    private int rid = 0;
    private String attachmentUri = null;
    private String attachmentMime = null;
    Handler handler;
    private MessagesSource messagesSource;
    private JuickMessage selectedReply;
    private long usageStart;
    GestureDetector detector;

    public ThreadActivity() {
        instanceCount++;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        JuickAdvancedApplication.maybeEnableAcceleration(this);
        JuickAdvancedApplication.setupTheme(this);
        //requestWindowFeature(Window.FEATURE_NO_TITLE);
        //getSherlock().requestFeature(Window.FEATURE_NO_TITLE);
        final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        super.onCreate(savedInstanceState);
        handler = new Handler();

        Intent i = getIntent();
        mid = (MessageID) i.getSerializableExtra("mid");
        if (mid == null) {
            finish();
        }

        messagesSource = (MessagesSource) i.getSerializableExtra("messagesSource");
        if (sp.getBoolean("fullScreenThread", false)) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        }
        setContentView(R.layout.thread);
        /*
                findViewById(R.id.gotoMain).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startActivity(new Intent(ThreadActivity.this, MainActivity.class));
        }
                });
        */
        final View buttons = findViewById(R.id.buttons);
        bSend = (ImageButton) findViewById(R.id.buttonSend);
        bSend.setOnClickListener(this);
        bAttach = (ImageButton) findViewById(R.id.buttonAttachment);
        bAttach.setOnClickListener(this);
        etMessage = (EditText) findViewById(R.id.editMessage);

        if (sp.getBoolean("helvNueFonts", false)) {
            etMessage.setTypeface(JuickAdvancedApplication.helvNue);
            /*
                        TextView oldTitle = (TextView)findViewById(R.id.old_title);
                        oldTitle.setTypeface(JuickAdvancedApplication.helvNue);
            */
        }

        Button cancel = (Button) findViewById(R.id.buttonCancel);
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doCancel();
            }
        });

        tvReplyTo = (TextView) findViewById(R.id.textReplyTo);
        replyToContainer = (RelativeLayout) findViewById(R.id.replyToContainer);
        setHeight(replyToContainer, 0);
        showThread = (Button) findViewById(R.id.showThread);
        draftsButton = (Button) findViewById(R.id.drafts);
        etMessage.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    etMessage.setHint("");
                    setHeight(buttons, ActionBar.LayoutParams.WRAP_CONTENT);
                    InputMethodManager inputMgr = (InputMethodManager) getSystemService(
                            Context.INPUT_METHOD_SERVICE);
                    inputMgr.toggleSoftInput(0, 0);
                } else {
                    etMessage.setHint(R.string.ClickToReply);
                    setHeight(buttons, 0);
                }
                //To change body of implemented methods use File | Settings | File Templates.
            }
        });
        draftsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                class Item {
                    String label;
                    long ts;
                    int index;

                    Item(String label, long ts, int index) {
                        this.label = label;
                        this.ts = ts;
                        this.index = index;
                    }
                }
                final ArrayList<Item> items = new ArrayList<Item>();
                final SharedPreferences drafts = getSharedPreferences("drafts", MODE_PRIVATE);
                for (int q = 0; q < 1000; q++) {
                    String msg = drafts.getString("message" + q, null);
                    if (msg != null) {
                        if (msg.length() > 50)
                            msg = msg.substring(0, 50);
                        items.add(new Item(msg, drafts.getLong("timestamp" + q, 0), q));
                    }
                }
                Collections.sort(items, new Comparator<Item>() {
                    @Override
                    public int compare(Item item, Item item2) {
                        final long l = item2.ts - item.ts;
                        return l == 0 ? 0 : l > 0 ? 1 : -1;
                    }
                });
                CharSequence[] arr = new CharSequence[items.size()];
                for (int i1 = 0; i1 < items.size(); i1++) {
                    Item item = items.get(i1);
                    arr[i1] = item.label;
                }
                new AlertDialog.Builder(ThreadActivity.this).setItems(arr, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, final int which) {
                        final Runnable doPull = new Runnable() {
                            @Override
                            public void run() {
                                pullDraft(null, drafts, items.get(which).index);
                                updateDraftsButton();
                            }
                        };
                        if (pulledDraft != null
                                && pulledDraft.trim().equals(etMessage.getText().toString().trim())) {
                            // no need to ask, user just looks at the drafts
                            saveDraft(pulledDraftRid, pulledDraftMid, pulledDraftTs, pulledDraft);
                            doPull.run();
                        } else {
                            if (etMessage.getText().toString().length() > 0) {
                                new AlertDialog.Builder(ThreadActivity.this)
                                        .setTitle(getString(R.string.ReplacingText))
                                        .setMessage(getString(R.string.YourTextWillBeReplaced))
                                        .setNegativeButton(android.R.string.ok,
                                                new DialogInterface.OnClickListener() {
                                                    @Override
                                                    public void onClick(DialogInterface dialog, int which) {
                                                        doPull.run();
                                                    }

                                                })
                                        .setNeutralButton(
                                                getString(pulledDraft != null ? R.string.SaveChangedDraft
                                                        : R.string.SaveDraft),
                                                new DialogInterface.OnClickListener() {
                                                    @Override
                                                    public void onClick(DialogInterface dialog, int which) {
                                                        if (pulledDraft != null) {
                                                            saveDraft(pulledDraftRid, pulledDraftMid,
                                                                    System.currentTimeMillis(),
                                                                    etMessage.getText().toString());
                                                        } else {
                                                            saveDraft(rid, mid.toString(),
                                                                    System.currentTimeMillis(),
                                                                    etMessage.getText().toString());
                                                        }
                                                        doPull.run();
                                                    }
                                                })
                                        .setPositiveButton(android.R.string.cancel,
                                                new DialogInterface.OnClickListener() {
                                                    @Override
                                                    public void onClick(DialogInterface dialog, int which) {
                                                    }
                                                })
                                        .show();
                            } else {
                                doPull.run();
                            }
                        }
                    }
                }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                }).show();
            }
        });
        enableDrafts = (sp.getBoolean("enableDrafts", false));
        if (sp.getBoolean("capitalizeReplies", false)) {
            etMessage.setInputType(etMessage.getInputType() | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES);
        }
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        tf = new ThreadFragment();
        tf.init(getLastCustomNonConfigurationInstance(), this);
        Bundle args = new Bundle();
        args.putSerializable("mid", mid);
        args.putSerializable("messagesSource", messagesSource);
        args.putSerializable("prefetched", i.getSerializableExtra("prefetched"));
        args.putSerializable("originalMessage", i.getSerializableExtra("originalMessage"));
        args.putBoolean("scrollToBottom", i.getBooleanExtra("scrollToBottom", false));
        tf.setArguments(args);
        ft.add(R.id.threadfragment, tf);
        ft.commit();
        MainActivity.restyleChildrenOrWidget(getWindow().getDecorView());
        detector = new GestureDetector(this, new GestureDetector.OnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e) {

            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return false;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {

            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                if (velocityX > 0 && Math.abs(velocityX) > 4 * Math.abs(velocityY) && Math.abs(velocityX) > 400) {
                    if (etMessage.getText().toString().trim().length() == 0) {
                        System.out.println("velocityX=" + velocityX + " velocityY" + velocityY);
                        if (sp.getBoolean("swipeToClose", true)) {
                            onBackPressed();
                        }
                    }
                }
                return false;
            }
        });

        com.actionbarsherlock.app.ActionBar actionBar = getSherlock().getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setLogo(R.drawable.back_button);

    }

    Runnable pendingTransition;

    void saveDraft(long saveRid, String saveMid, long saveTs, String messag) {
        final SharedPreferences drafts = getSharedPreferences("drafts", MODE_PRIVATE);
        for (int i = 0; i < 1000; i++) {
            final String string = drafts.getString("message" + i, null);
            if (string == null) {
                drafts.edit().putString("message" + i, messag).putLong("timestamp" + i, saveTs)
                        .putLong("rid" + i, saveRid).putString("mid" + i, saveMid).commit();
                break;
            }
        }
    }

    public void doCancel() {
        etMessage.clearFocus();
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(etMessage.getWindowToken(), 0);
    }

    /*
        private void launchMainMessagesEnabler() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            findViewById(R.id.gotoMain).setVisibility(MainActivity.nActiveMainActivities == 0 ? View.VISIBLE : View.GONE);
            if (resumed)
                handler.postDelayed(this, 1000);
        }
    });
        }
    */

    void resetForm() {
        rid = 0;
        replyInProgress = null;
        selectedReply = null;
        setHeight(replyToContainer, 0);
        etMessage.setText("");
        attachmentMime = null;
        attachmentUri = null;
        bAttach.setSelected(false);
        setFormEnabled(true);
    }

    boolean resumed = false;

    @Override
    protected void onResume() {
        resumed = true;
        MainActivity.restyleChildrenOrWidget(getWindow().getDecorView());
        //launchMainMessagesEnabler();
        super.onResume(); //To change body of overridden methods use File | Settings | File Templates.
        usageStart = System.currentTimeMillis();
    }

    @Override
    protected void onPause() {
        super.onPause();
        resumed = false;
        long usedTime = System.currentTimeMillis() - usageStart;
        if (messagesSource != null) {
            new WhatsNew(this).increaseUsage(this, "activity_time_" + messagesSource.getKind() + "_thread",
                    usedTime);
        }
    }

    public void setFormEnabled(boolean state) {
        etMessage.setEnabled(state);
        bSend.setEnabled(state);
    }

    boolean focusedOnceOnPrefetched = false;

    public void onThreadLoaded(JuickMessage message) {
        String title = "@" + message.User.UName;
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        boolean showNumbers = sp.getBoolean("showNumbers", false);
        if (showNumbers)
            title += " - " + message.getDisplayMessageNo() + " - " + com.juickadvanced.Utils
                    .toRelaviteDate(message.Timestamp.getTime(), XMPPIncomingMessagesActivity.isRussian());
        //TextView oldTitle = (TextView)findViewById(R.id.old_title);
        setTitle(title);
        //oldTitle.setText(title);
        DatabaseService.rememberVisited(message);
        final Intent i = getIntent();
        final Serializable prefetched = i.getSerializableExtra("prefetched");
        JuickMessage prefetchedReply = null;
        if (prefetched != null && !focusedOnceOnPrefetched) {
            focusedOnceOnPrefetched = true;
            prefetchedReply = (JuickMessage) tf.getListView().getAdapter()
                    .getItem(tf.getListView().getAdapter().getCount() - 1);
            onReplySelected(prefetchedReply);
            etMessage.requestFocus();
        }
        final String midS = mid.toString();
        final SharedPreferences drafts = getSharedPreferences("drafts", MODE_PRIVATE);
        for (int q = 0; q < 1000; q++) {
            final String savedMID = drafts.getString("mid" + q, null);
            if (savedMID != null && savedMID.equals(midS)) {
                pullDraft(prefetchedReply, drafts, q);
                break;
            }
        }
        updateDraftsButton();
    }

    private void updateDraftsButton() {
        final SharedPreferences drafts = getSharedPreferences("drafts", MODE_PRIVATE);
        draftsButton.setVisibility(drafts.getAll().size() > 0 && enableDrafts ? View.VISIBLE : View.GONE);
    }

    /**
     * @param prefetchedReply nullable, for prefetch mode only
     * @param drafts oh
     * @param q     draft index
     */
    private void pullDraft(JuickMessage prefetchedReply, SharedPreferences drafts, int q) {
        final long savedRid = drafts.getLong("rid" + q, 0);
        boolean matchingRid = prefetchedReply == null;
        for (int msg = 0; msg < tf.getListView().getAdapter().getCount(); msg++) {
            final Object item = tf.getListView().getAdapter().getItem(msg);
            if (item instanceof JuickMessage) {
                JuickMessage someReply = (JuickMessage) item;
                if (someReply.getRID() == savedRid) {
                    onReplySelected(someReply);
                    if (prefetchedReply != null && prefetchedReply.getRID() == someReply.getRID()) {
                        matchingRid = true;
                    }
                    break;
                }
            }
        }
        if (matchingRid) {
            etMessage.setText(pulledDraft = drafts.getString("message" + q, null));
            pulledDraftMid = drafts.getString("mid" + q, null);
            pulledDraftRid = drafts.getLong("rid" + q, 0);
            pulledDraftTs = drafts.getLong("timestamp" + q, 0);
            etMessage.requestFocus();
            drafts.edit().remove("message" + q).remove("timestamp" + q).remove("rid" + q).remove("mid" + q)
                    .commit();
        }
    }

    public void onReplySelected(final JuickMessage msg) {
        selectedReply = msg;
        rid = msg.getRID();
        if (rid > 0) {
            SpannableStringBuilder ssb = new SpannableStringBuilder();
            String inreplyto = getResources().getString(R.string.In_reply_to_) + " ";
            ssb.append(inreplyto).append(msg.Text);
            ssb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, inreplyto.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            tvReplyTo.setText(ssb);
            setHeight(replyToContainer, ActionBar.LayoutParams.WRAP_CONTENT);
            showThread.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    tf.showThread(msg, false);
                }
            });
        } else {
            setHeight(replyToContainer, 0);
        }
    }

    private void setHeight(View view, int heightHint) {
        view.getLayoutParams().height = heightHint;
        view.setLayoutParams(view.getLayoutParams());
    }

    @Override
    public Object onRetainCustomNonConfigurationInstance() {
        if (tf != null) {
            return tf.saveState();
        }
        return super.onRetainCustomNonConfigurationInstance(); //To change body of overridden methods use File | Settings | File Templates.
    }

    public void onClick(View view) {
        if (view == bAttach) {
            if (attachmentUri == null) {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.Attach);
                builder.setAdapter(new AttachAdapter(this), this);
                builder.show();
            } else {
                attachmentUri = null;
                attachmentMime = null;
                bAttach.setSelected(false);
            }
        } else if (view == bSend) {
            final String msg = etMessage.getText().toString();
            if (msg.length() < 1) {
                Toast.makeText(this, R.string.Enter_a_message, Toast.LENGTH_SHORT).show();
                return;
            }
            final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
            try {
                if (sp.getBoolean("warnRepliesToBody", false) && rid == 0
                        && tf.getListView().getAdapter().getCount() > 3) {
                    new AlertDialog.Builder(this).setTitle("Post reply")
                            .setMessage("Replying to topic starter? (or select recipient)").setCancelable(true)
                            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                }
                            }).setPositiveButton("Continue", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                    previewAndSendReply(msg);
                                }
                            }).show();
                } else {
                    previewAndSendReply(msg);
                }
            } catch (Exception e) {
                Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void previewAndSendReply(final String msg) {
        final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        if (sp.getBoolean("previewReplies", false)) {
            final TextView tv = new TextView(this);
            JuickMessage jm = new JuickMessage();
            jm.User = new JuickUser();
            jm.User.UName = "You";
            jm.Text = msg;
            jm.tags = new Vector<String>();
            if (rid != 0) {
                // insert destination user name
                JuickMessage reply = tf.findReply(tf.getListView(), rid);
                if (reply != null) {
                    jm.Text = "@" + reply.User.UName + " " + jm.Text;
                }
            }
            JuickMessagesAdapter.ParsedMessage parsedMessage = JuickMessagesAdapter.formatMessageText(this, jm,
                    true);
            tv.setText(parsedMessage.textContent);
            tv.setPadding(10, 10, 10, 10);
            MainActivity.restyleChildrenOrWidget(tv);
            final AlertDialog dialog = new AlertDialog.Builder(
                    new ContextThemeWrapper(this, R.style.Theme_Sherlock_Light)).setTitle("Post reply - preview")
                            .setView(tv).setCancelable(true)
                            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                }
                            }).setPositiveButton("Post reply", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                    sendReplyMain(msg);
                                }
                            }).create();
            dialog.setOnShowListener(new DialogInterface.OnShowListener() {
                @Override
                public void onShow(DialogInterface i) {
                    tv.setBackgroundColor(JuickMessagesAdapter.getColorTheme(dialog.getContext()).getBackground());
                    MainActivity.restyleChildrenOrWidget(tv);
                }
            });
            dialog.show();
        } else {
            sendReplyMain(msg);
        }
    }

    public MicroBlog.OperationInProgress replyInProgress;

    private void sendReplyMain(String msg) {
        if (tf.listAdapter.getCount() > 0) {
            setFormEnabled(false);
            final JuickMessage threadStarter = tf.listAdapter.getItem(0);
            replyInProgress = MainActivity.getMicroBlog(mid.getMicroBlogCode()).postReply(this, mid, threadStarter,
                    selectedReply, msg, attachmentUri, attachmentMime, new Utils.Function<Void, String>() {
                        @Override
                        public Void apply(String error) {
                            replyInProgress = null;
                            if (error == null) {
                                Utils.ServiceGetter<DatabaseService> databaseGetter = new Utils.ServiceGetter<DatabaseService>(
                                        ThreadActivity.this, DatabaseService.class);
                                databaseGetter.getService(new Utils.ServiceGetter.Receiver<DatabaseService>() {
                                    @Override
                                    public void withService(DatabaseService service) {
                                        service.saveRecentlyCommentedThread(threadStarter);
                                    }

                                });
                                sendMessageSucceed();
                            } else {
                                setFormEnabled(true);
                                if (attachmentUri != null) {
                                    try {
                                        AlertDialog.Builder builder = new AlertDialog.Builder(ThreadActivity.this);
                                        builder.setNeutralButton(R.string.OK, null);
                                        builder.setIcon(android.R.drawable.ic_dialog_alert);
                                        builder.setMessage(error);
                                        builder.show();
                                    } catch (Exception e) {
                                        // activity must be dead already
                                    }
                                } else {
                                    Toast.makeText(ThreadActivity.this, error, Toast.LENGTH_LONG).show();
                                }
                            }
                            return null;
                        }
                    });
        } else {
            Toast.makeText(this, "Pardon!", Toast.LENGTH_LONG);
        }
    }

    public void sendMessageSucceed() {
        resetForm();
        if (attachmentUri == null) {
            Toast.makeText(this, R.string.Message_posted, Toast.LENGTH_LONG).show();
        } else {
            NewMessageActivity.getPhotoCaptureFile().delete(); // if any
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setNeutralButton(R.string.OK, null);
            builder.setIcon(android.R.drawable.ic_dialog_info);
            builder.setMessage(R.string.Message_posted);
            AlertDialog alertDialog = builder.create();
            alertDialog.show();
        }
        doCancel();
    }

    public void onClick(DialogInterface dialog, int which) {
        Intent intent;
        switch (which) {
        case 0:
            intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/*");
            startActivityForResult(Intent.createChooser(intent, null), ACTIVITY_ATTACHMENT_IMAGE);
            break;
        case 1:
            intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
            boolean useTempFileForCapture = sp.getBoolean("useTempFileForCapture", true);
            if (useTempFileForCapture) {
                File file = NewMessageActivity.getPhotoCaptureFile();
                file.delete();
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
            } else {
                intent.putExtra(MediaStore.EXTRA_OUTPUT,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            }
            startActivityForResult(intent, ACTIVITY_ATTACHMENT_IMAGE);
            break;
        case 2:
            intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("video/*");
            startActivityForResult(Intent.createChooser(intent, null), ACTIVITY_ATTACHMENT_VIDEO);
            break;
        case 3:
            intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
            startActivityForResult(intent, ACTIVITY_ATTACHMENT_VIDEO);
            break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if ((requestCode == ACTIVITY_ATTACHMENT_IMAGE || requestCode == ACTIVITY_ATTACHMENT_VIDEO)) {
                if (data != null) {
                    attachmentUri = data.getDataString();
                } else if (NewMessageActivity.getPhotoCaptureFile().exists()) {
                    attachmentUri = Uri.fromFile(NewMessageActivity.getPhotoCaptureFile()).toString();
                }
                if (requestCode == ACTIVITY_ATTACHMENT_IMAGE) {
                    NewMessageActivity.maybeResizePicture(this, attachmentUri, new Utils.Function<Void, String>() {
                        @Override
                        public Void apply(String s) {
                            attachmentUri = s;
                            bAttach.setSelected(attachmentUri != null);
                            return null;
                        }
                    });
                }
                attachmentMime = (requestCode == ACTIVITY_ATTACHMENT_IMAGE) ? "image/jpeg" : "video/3gpp";
                bAttach.setSelected(attachmentUri != null);
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.thread, menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.findItem(R.id.sort_by_rating).setVisible(messagesSource instanceof MessagesSource.SorterByRating);
        menu.findItem(R.id.sort_by_date_dec).setVisible(messagesSource instanceof MessagesSource.SorterByDateDesc);
        menu.findItem(R.id.sort_by_date_inc).setVisible(messagesSource instanceof MessagesSource.SorterByDateAsc);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
        switch (item.getItemId()) {
        case R.id.sort_by_rating:
            sortComments(((MessagesSource.SorterByRating) messagesSource).getSorterByRating());
            return true;
        case R.id.sort_by_date_dec:
            sortComments(((MessagesSource.SorterByDateDesc) messagesSource).getSorterByDateDesc());
            return true;
        case R.id.sort_by_date_inc:
            sortComments(((MessagesSource.SorterByDateAsc) messagesSource).getSorterByDateAsc());
            return true;
        case R.id.menuitem_preferences:
            Intent prefsIntent = new Intent(this, NewJuickPreferenceActivity.class);
            prefsIntent.putExtra("menu", NewJuickPreferenceActivity.Menu.TOP_LEVEL.name());
            startActivity(prefsIntent);
            return true;
        case android.R.id.home:
            finish();
            overridePendingTransition(R.anim.enter_raise_and_light, R.anim.leave_slide_to_right);
            if (MainActivity.nActiveMainActivities == 0) {
                startActivity(new Intent(ThreadActivity.this, MainActivity.class));
            }
            return true;
        case R.id.reload:
            tf.reload();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private void sortComments(MessagesSource.Sorter sorter) {
        tf.sortMessages(sorter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        instanceCount--;
    }

    @Override
    public void requestWindowFeature(long featureId) {
        // actionbar sherlock deducing flag from theme id.
        if (featureId == com.actionbarsherlock.view.Window.FEATURE_ACTION_BAR)
            return;
        super.requestWindowFeature(featureId);
    }

    @Override
    public boolean onListTouchEvent(View view, MotionEvent event) {
        return detector.onTouchEvent(event) || super.onListTouchEvent(view, event);
    }

    @Override
    public void onBackPressed() {
        if (tf.onBackPressed())
            return;
        if (tf != null && tf.listAdapter.imagePreviewHelper != null
                && tf.listAdapter.imagePreviewHelper.handleBack())
            return;
        if (enableDrafts) {
            final String messag = etMessage.getText().toString().trim();
            if (messag.length() > 0) {
                if (pulledDraft != null && pulledDraft.trim().equals(etMessage.getText().toString().trim())) {
                    saveDraft(pulledDraftRid, pulledDraftMid, pulledDraftTs, pulledDraft);
                } else {
                    new AlertDialog.Builder(this).setTitle(getString(R.string.LeavingThread))
                            .setMessage(getString(R.string.YourReplyIsNotSent))
                            .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                }
                            })
                            .setNeutralButton(getString(R.string.SaveDraft), new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    if (pulledDraft != null) {
                                        saveDraft(pulledDraftRid, pulledDraftMid, System.currentTimeMillis(),
                                                messag);
                                    } else {
                                        saveDraft(rid, mid.toString(), System.currentTimeMillis(), messag);
                                    }
                                    finish();
                                }
                            }).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    finish();
                                }
                            }).show();
                    return;
                }
            }
        }
        try {
            super.onBackPressed(); //To change body of overridden methods use File | Settings | File Templates.
        } catch (Throwable e) {
            MainActivity.handleException(e);
        }
        overridePendingTransition(R.anim.enter_raise_and_light, R.anim.leave_slide_to_right);
    }
}