im.vector.fragments.VectorMessageListFragment.java Source code

Java tutorial

Introduction

Here is the source code for im.vector.fragments.VectorMessageListFragment.java

Source

/*
 * Copyright 2015 OpenMarket 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 im.vector.fragments;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
import android.support.v4.app.FragmentManager;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;

import org.matrix.androidsdk.MXSession;
import org.matrix.androidsdk.adapters.MessageRow;
import org.matrix.androidsdk.adapters.MessagesAdapter;
import org.matrix.androidsdk.data.RoomState;
import org.matrix.androidsdk.db.MXMediasCache;
import org.matrix.androidsdk.fragments.MatrixMessageListFragment;
import org.matrix.androidsdk.fragments.MatrixMessagesFragment;
import org.matrix.androidsdk.listeners.MXMediaDownloadListener;
import org.matrix.androidsdk.rest.callback.ApiCallback;
import org.matrix.androidsdk.rest.callback.SimpleApiCallback;
import org.matrix.androidsdk.rest.model.Event;
import org.matrix.androidsdk.rest.model.FileMessage;
import org.matrix.androidsdk.rest.model.ImageMessage;
import org.matrix.androidsdk.rest.model.MatrixError;
import org.matrix.androidsdk.rest.model.Message;
import org.matrix.androidsdk.rest.model.VideoMessage;
import org.matrix.androidsdk.util.JsonUtils;
import im.vector.Matrix;
import im.vector.R;
import im.vector.VectorApp;
import im.vector.activity.CommonActivityUtils;
import im.vector.activity.MXCActionBarActivity;
import im.vector.activity.VectorHomeActivity;
import im.vector.activity.VectorMemberDetailsActivity;
import im.vector.activity.VectorRoomActivity;
import im.vector.activity.VectorMediasViewerActivity;
import im.vector.adapters.VectorMessagesAdapter;
import im.vector.db.VectorContentProvider;
import im.vector.receiver.VectorUniversalLinkReceiver;
import im.vector.util.SlidableMediaInfo;
import im.vector.util.VectorUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;

public class VectorMessageListFragment extends MatrixMessageListFragment
        implements VectorMessagesAdapter.VectorMessagesAdapterActionsListener {
    private static final String LOG_TAG = "VectorMessageListFrg";

    public interface IListFragmentEventListener {
        void onListTouch();
    }

    private static final String TAG_FRAGMENT_RECEIPTS_DIALOG = "TAG_FRAGMENT_RECEIPTS_DIALOG";
    private IListFragmentEventListener mHostActivityListener;

    // onMediaAction actions
    // private static final int ACTION_VECTOR_SHARE = R.id.ic_action_vector_share;
    private static final int ACTION_VECTOR_FORWARD = R.id.ic_action_vector_forward;
    private static final int ACTION_VECTOR_SAVE = R.id.ic_action_vector_save;
    public static final int ACTION_VECTOR_OPEN = 123456;

    // spinners
    private View mBackProgressView;
    private View mForwardProgressView;
    private View mMainProgressView;

    public static VectorMessageListFragment newInstance(String matrixId, String roomId, String eventId,
            String previewMode, int layoutResId) {
        VectorMessageListFragment f = new VectorMessageListFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_LAYOUT_ID, layoutResId);
        args.putString(ARG_MATRIX_ID, matrixId);
        args.putString(ARG_ROOM_ID, roomId);

        if (null != eventId) {
            args.putString(ARG_EVENT_ID, eventId);
        }

        if (null != previewMode) {
            args.putString(ARG_PREVIEW_MODE_ID, previewMode);
        }

        f.setArguments(args);
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(LOG_TAG, "onCreateView");

        View v = super.onCreateView(inflater, container, savedInstanceState);

        Bundle args = getArguments();

        // when an event id is defined, display a thick green line to its left
        if (args.containsKey(ARG_EVENT_ID) && (mAdapter instanceof VectorMessagesAdapter)) {
            ((VectorMessagesAdapter) mAdapter).setSearchedEventId(args.getString(ARG_EVENT_ID, ""));
        }

        return v;
    }

    @Override
    public MatrixMessagesFragment createMessagesFragmentInstance(String roomId) {
        return VectorMessagesFragment.newInstance(getSession(), roomId, this);
    }

    /**
     * @return the fragment tag to use to restore the matrix messages fragment
     */
    protected String getMatrixMessagesFragmentTag() {
        return getClass().getName() + ".MATRIX_MESSAGE_FRAGMENT_TAG";
    }

    /**
     * Called when a fragment is first attached to its activity.
     * {@link #onCreate(Bundle)} will be called after this.
     *
     * @param aHostActivity parent activity
     */
    @Override
    public void onAttach(Activity aHostActivity) {
        super.onAttach(aHostActivity);
        try {
            mHostActivityListener = (IListFragmentEventListener) aHostActivity;
        } catch (ClassCastException e) {
            // if host activity does not provide the implementation, just ignore it
            Log.w(LOG_TAG,
                    "## onAttach(): host activity does not implement IListFragmentEventListener " + aHostActivity);
            mHostActivityListener = null;
        }

        mBackProgressView = aHostActivity.findViewById(R.id.loading_room_paginate_back_progress);
        mForwardProgressView = aHostActivity.findViewById(R.id.loading_room_paginate_forward_progress);
        mMainProgressView = aHostActivity.findViewById(R.id.main_progress_layout);
    }

    @Override
    public void onPause() {
        super.onPause();

        if (mAdapter instanceof VectorMessagesAdapter) {
            ((VectorMessagesAdapter) mAdapter).onPause();
        }
    }

    /**
     * Called when the fragment is no longer attached to its activity.  This
     * is called after {@link #onDestroy()}.
     */
    @Override
    public void onDetach() {
        super.onDetach();
        mHostActivityListener = null;
    }

    @Override
    public MXSession getSession(String matrixId) {
        return Matrix.getMXSession(getActivity(), matrixId);
    }

    @Override
    public MXMediasCache getMXMediasCache() {
        return Matrix.getInstance(getActivity()).getMediasCache();
    }

    @Override
    public MessagesAdapter createMessagesAdapter() {
        VectorMessagesAdapter vectorMessagesAdapter = new VectorMessagesAdapter(mSession, getActivity(),
                getMXMediasCache());
        vectorMessagesAdapter.setVectorMessagesAdapterActionsListener(this);
        return vectorMessagesAdapter;
    }

    /**
     * The user scrolls the list.
     * Apply an expected behaviour
     * @param event the scroll event
     */
    @Override
    public void onListTouch(MotionEvent event) {
        // the user scroll over the keyboard
        // hides the keyboard
        if (mCheckSlideToHide && (event.getY() > mMessageListView.getHeight())) {
            mCheckSlideToHide = false;
            MXCActionBarActivity.dismissKeyboard(getActivity());
        }

        // notify host activity
        if (null != mHostActivityListener)
            mHostActivityListener.onListTouch();
    }

    /**
     * Cancel the messages selection mode.
     */
    public void cancelSelectionMode() {
        ((VectorMessagesAdapter) mAdapter).cancelSelectionMode();
    }

    /**
     * An action has been  triggered on an event.
     * @param event the event.
     * @param textMsg the event text
     * @param action an action ic_action_vector_XXX
     */
    public void onEventAction(final Event event, final String textMsg, final int action) {
        if (action == R.id.ic_action_vector_resend_message) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    resend(event);
                }
            });
        } else if (action == R.id.ic_action_vector_redact_message) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (event.isUndeliverable()) {
                        // delete from the store
                        mSession.getDataHandler().getStore().deleteEvent(event);
                        mSession.getDataHandler().getStore().commit();

                        // remove from the adapter
                        mAdapter.removeEventById(event.eventId);
                        mAdapter.notifyDataSetChanged();
                        mEventSendingListener.onMessageRedacted(event);
                    } else {
                        redactEvent(event.eventId);
                    }
                }
            });
        } else if (action == R.id.ic_action_vector_copy) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    VectorUtils.copyToClipboard(getActivity(), textMsg);
                }
            });
        } else if ((action == R.id.ic_action_vector_cancel_upload)
                || (action == R.id.ic_action_vector_cancel_download)) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    new AlertDialog.Builder(VectorApp.getCurrentActivity())
                            .setMessage((action == R.id.ic_action_vector_cancel_upload)
                                    ? R.string.attachment_cancel_upload
                                    : R.string.attachment_cancel_download)
                            .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                    mRoom.cancelEventSending(event);

                                    getActivity().runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            mAdapter.notifyDataSetChanged();
                                        }
                                    });
                                }
                            }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                }
                            }).create().show();
                }
            });
        } else if (action == R.id.ic_action_vector_quote) {
            Activity attachedActivity = getActivity();

            if ((null != attachedActivity) && (attachedActivity instanceof VectorRoomActivity)) {
                Message message = JsonUtils.toMessage(event.content);
                ((VectorRoomActivity) attachedActivity).initEditText("> " + message.body + "\n\n");
            }
        } else if ((action == R.id.ic_action_vector_share) || (action == R.id.ic_action_vector_forward)
                || (action == R.id.ic_action_vector_save)) {
            //
            Message message = JsonUtils.toMessage(event.content);

            String mediaUrl = null;
            String mediaMimeType = null;

            if (message instanceof ImageMessage) {
                ImageMessage imageMessage = (ImageMessage) message;

                mediaUrl = imageMessage.url;
                mediaMimeType = imageMessage.getMimeType();
            } else if (message instanceof VideoMessage) {
                VideoMessage videoMessage = (VideoMessage) message;

                mediaUrl = videoMessage.url;

                if (null != videoMessage.info) {
                    mediaMimeType = videoMessage.info.mimetype;
                }
            } else if (message instanceof FileMessage) {
                FileMessage fileMessage = (FileMessage) message;

                mediaUrl = fileMessage.url;
                mediaMimeType = fileMessage.getMimeType();
            }

            // media file ?
            if (null != mediaUrl) {
                onMediaAction(action, mediaUrl, mediaMimeType, message.body);
            } else if ((action == R.id.ic_action_vector_share) || (action == R.id.ic_action_vector_forward)
                    || (action == R.id.ic_action_vector_quote)) {
                // use the body
                final Intent sendIntent = new Intent();

                sendIntent.setAction(Intent.ACTION_SEND);
                sendIntent.putExtra(Intent.EXTRA_TEXT, message.body);
                sendIntent.setType("text/plain");

                if ((action == R.id.ic_action_vector_forward) || (action == R.id.ic_action_vector_quote)) {
                    CommonActivityUtils.sendFilesTo(getActivity(), sendIntent);
                } else {
                    startActivity(sendIntent);
                }
            }
        } else if (action == R.id.ic_action_vector_permalink) {
            VectorUtils.copyToClipboard(getActivity(), VectorUtils.getPermalink(event.roomId, event.eventId));
        } else if (action == R.id.ic_action_vector_report) {
            onMessageReport(event);
        } else if (action == R.id.ic_action_view_source) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

                    View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_event_content, null);
                    TextView textview = (TextView) view.findViewById(R.id.event_content_text_view);

                    Gson gson = new GsonBuilder().setPrettyPrinting().create();
                    textview.setText(gson.toJson(JsonUtils.toJson(event)));
                    builder.setView(view);

                    builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });

                    builder.create().show();
                }
            });
        }
    }

    /**
     * The user reports a content problem to the server
     * @param event the event to report
     */
    private void onMessageReport(final Event event) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(R.string.room_event_action_report_prompt_reason);

        // add a text input
        final EditText input = new EditText(getActivity());
        builder.setView(input);

        builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                final String reason = input.getText().toString();

                mRoom.report(event.eventId, -100, reason, new SimpleApiCallback<Void>(getActivity()) {
                    @Override
                    public void onSuccess(Void info) {
                        new AlertDialog.Builder(VectorApp.getCurrentActivity())
                                .setMessage(R.string.room_event_action_report_prompt_ignore_user)
                                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();

                                        ArrayList<String> userIdsList = new ArrayList<>();
                                        userIdsList.add(event.sender);

                                        mSession.ignoreUsers(userIdsList, new SimpleApiCallback<Void>() {
                                            @Override
                                            public void onSuccess(Void info) {
                                            }
                                        });
                                    }
                                }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                    }
                                }).create().show();
                    }
                });
            }
        });
        builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        builder.show();
    }

    /***
     * Manage save / share / forward actions on a media file
     * @param menuAction the menu action ACTION_VECTOR__XXX
     * @param mediaUrl the media URL (must be not null)
     * @param mediaMimeType the mime type
     * @param filename the filename
     */
    protected void onMediaAction(final int menuAction, final String mediaUrl, final String mediaMimeType,
            final String filename) {
        MXMediasCache mediasCache = Matrix.getInstance(getActivity()).getMediasCache();
        File file = mediasCache.mediaCacheFile(mediaUrl, mediaMimeType);

        // check if the media has already been downloaded
        if (null != file) {
            // download
            if ((menuAction == ACTION_VECTOR_SAVE) || (menuAction == ACTION_VECTOR_OPEN)) {
                String savedMediaPath = CommonActivityUtils.saveMediaIntoDownloads(getActivity(), file, filename,
                        mediaMimeType);

                if (null != savedMediaPath) {
                    if (menuAction == ACTION_VECTOR_SAVE) {
                        Toast.makeText(getActivity(), getText(R.string.media_slider_saved), Toast.LENGTH_LONG)
                                .show();
                    } else {
                        CommonActivityUtils.openMedia(getActivity(), savedMediaPath, mediaMimeType);
                    }
                }
            } else {
                // shared / forward
                Uri mediaUri = null;

                File renamedFile = file;

                if (!TextUtils.isEmpty(filename)) {
                    try {
                        InputStream fin = new FileInputStream(file);
                        String tmpUrl = mediasCache.saveMedia(fin, filename, mediaMimeType);

                        if (null != tmpUrl) {
                            renamedFile = mediasCache.mediaCacheFile(tmpUrl, mediaMimeType);
                        }
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "onMediaAction shared / forward failed : " + e.getLocalizedMessage());
                    }
                }

                if (null != renamedFile) {
                    try {
                        mediaUri = VectorContentProvider.absolutePathToUri(getActivity(),
                                renamedFile.getAbsolutePath());
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "onMediaAction VectorContentProvider.absolutePathToUri: "
                                + e.getLocalizedMessage());
                    }
                }

                if (null != mediaUri) {
                    final Intent sendIntent = new Intent();
                    sendIntent.setAction(Intent.ACTION_SEND);
                    sendIntent.setType(mediaMimeType);
                    sendIntent.putExtra(Intent.EXTRA_STREAM, mediaUri);

                    if (menuAction == ACTION_VECTOR_FORWARD) {
                        CommonActivityUtils.sendFilesTo(getActivity(), sendIntent);
                    } else {
                        startActivity(sendIntent);
                    }
                }
            }
        } else {
            // else download it
            final String downloadId = mediasCache.downloadMedia(getActivity(), mSession.getHomeserverConfig(),
                    mediaUrl, mediaMimeType);
            mAdapter.notifyDataSetChanged();

            if (null != downloadId) {
                mediasCache.addDownloadListener(downloadId, new MXMediaDownloadListener() {
                    @Override
                    public void onDownloadError(String downloadId, JsonElement jsonElement) {
                        MatrixError error = JsonUtils.toMatrixError(jsonElement);

                        if ((null != error) && error.isSupportedErrorCode()) {
                            Toast.makeText(VectorMessageListFragment.this.getActivity(),
                                    error.getLocalizedMessage(), Toast.LENGTH_LONG).show();
                        }
                    }

                    @Override
                    public void onDownloadComplete(String aDownloadId) {
                        if (aDownloadId.equals(downloadId)) {

                            VectorMessageListFragment.this.getActivity().runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    onMediaAction(menuAction, mediaUrl, mediaMimeType, filename);
                                }
                            });
                        }
                    }
                });
            }
        }
    }

    /**
     * return true to display all the events.
     * else the unknown events will be hidden.
     */
    @Override
    public boolean isDisplayAllEvents() {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        return preferences.getBoolean(getString(R.string.settings_key_display_all_events), false);
    }

    private void setViewVisibility(View view, int visibility) {
        if ((null != view) && (null != getActivity())) {
            view.setVisibility(visibility);
        }
    }

    @Override
    public void showLoadingBackProgress() {
        setViewVisibility(mBackProgressView, View.VISIBLE);
    }

    @Override
    public void hideLoadingBackProgress() {
        setViewVisibility(mBackProgressView, View.GONE);
    }

    @Override
    public void showLoadingForwardProgress() {
        setViewVisibility(mForwardProgressView, View.VISIBLE);
    }

    @Override
    public void hideLoadingForwardProgress() {
        setViewVisibility(mForwardProgressView, View.GONE);
    }

    @Override
    public void showInitLoading() {
        setViewVisibility(mMainProgressView, View.VISIBLE);
    }

    @Override
    public void hideInitLoading() {
        setViewVisibility(mMainProgressView, View.GONE);
    }

    public boolean onRowLongClick(int position) {
        return false;
    }

    /**
     * @return the image and video messages list
     */
    protected ArrayList<SlidableMediaInfo> listSlidableMessages() {
        ArrayList<SlidableMediaInfo> res = new ArrayList<>();

        for (int position = 0; position < mAdapter.getCount(); position++) {
            MessageRow row = mAdapter.getItem(position);
            Message message = JsonUtils.toMessage(row.getEvent().content);

            if (Message.MSGTYPE_IMAGE.equals(message.msgtype)) {
                ImageMessage imageMessage = (ImageMessage) message;

                SlidableMediaInfo info = new SlidableMediaInfo();
                info.mMessageType = Message.MSGTYPE_IMAGE;
                info.mFileName = imageMessage.body;
                info.mMediaUrl = imageMessage.url;
                info.mRotationAngle = imageMessage.getRotation();
                info.mOrientation = imageMessage.getOrientation();
                info.mMimeType = imageMessage.getMimeType();
                info.mIdentifier = row.getEvent().eventId;
                res.add(info);
            } else if (Message.MSGTYPE_VIDEO.equals(message.msgtype)) {
                SlidableMediaInfo info = new SlidableMediaInfo();
                VideoMessage videoMessage = (VideoMessage) message;
                info.mMessageType = Message.MSGTYPE_VIDEO;
                info.mFileName = videoMessage.body;
                info.mMediaUrl = videoMessage.url;
                info.mThumbnailUrl = (null != videoMessage.info) ? videoMessage.info.thumbnail_url : null;
                info.mMimeType = videoMessage.getVideoMimeType();
                res.add(info);
            }
        }

        return res;
    }

    /**
     * Returns the mediaMessage position in listMediaMessages.
     * @param mediaMessagesList the media messages list
     * @param mediaMessage the imageMessage
     * @return the imageMessage position. -1 if not found.
     */
    protected int getMediaMessagePosition(ArrayList<SlidableMediaInfo> mediaMessagesList, Message mediaMessage) {
        String url = null;

        if (mediaMessage instanceof ImageMessage) {
            url = ((ImageMessage) mediaMessage).url;
        } else if (mediaMessage instanceof VideoMessage) {
            url = ((VideoMessage) mediaMessage).url;
        }

        // sanity check
        if (null == url) {
            return -1;
        }

        for (int index = 0; index < mediaMessagesList.size(); index++) {
            if (mediaMessagesList.get(index).mMediaUrl.equals(url)) {
                return index;
            }
        }

        return -1;
    }

    @Override
    public void onRowClick(int position) {
        MessageRow row = mAdapter.getItem(position);
        Event event = row.getEvent();

        // switch in section mode
        ((VectorMessagesAdapter) mAdapter).onEventTap(event.eventId);
    }

    @Override
    public void onContentClick(int position) {
        MessageRow row = mAdapter.getItem(position);
        Event event = row.getEvent();

        VectorMessagesAdapter vectorMessagesAdapter = (VectorMessagesAdapter) mAdapter;

        if (vectorMessagesAdapter.isInSelectionMode()) {
            // cancel the selection mode.
            vectorMessagesAdapter.onEventTap(null);
            return;
        }

        Message message = JsonUtils.toMessage(event.content);

        // video and images are displayed inside a medias slider.
        if (Message.MSGTYPE_IMAGE.equals(message.msgtype) || (Message.MSGTYPE_VIDEO.equals(message.msgtype))) {
            ArrayList<SlidableMediaInfo> mediaMessagesList = listSlidableMessages();
            int listPosition = getMediaMessagePosition(mediaMessagesList, message);

            if (listPosition >= 0) {
                Intent viewImageIntent = new Intent(getActivity(), VectorMediasViewerActivity.class);

                viewImageIntent.putExtra(VectorMediasViewerActivity.EXTRA_MATRIX_ID,
                        mSession.getCredentials().userId);
                viewImageIntent.putExtra(VectorMediasViewerActivity.KEY_THUMBNAIL_WIDTH,
                        mAdapter.getMaxThumbnailWith());
                viewImageIntent.putExtra(VectorMediasViewerActivity.KEY_THUMBNAIL_HEIGHT,
                        mAdapter.getMaxThumbnailHeight());
                viewImageIntent.putExtra(VectorMediasViewerActivity.KEY_INFO_LIST, mediaMessagesList);
                viewImageIntent.putExtra(VectorMediasViewerActivity.KEY_INFO_LIST_INDEX, listPosition);

                getActivity().startActivity(viewImageIntent);
            }
        } else if (Message.MSGTYPE_FILE.equals(message.msgtype)) {
            FileMessage fileMessage = JsonUtils.toFileMessage(event.content);

            if (null != fileMessage.url) {
                onMediaAction(ACTION_VECTOR_OPEN, fileMessage.url, fileMessage.getMimeType(), fileMessage.body);
            }
        } else {
            // switch in section mode
            vectorMessagesAdapter.onEventTap(event.eventId);
        }
    }

    @Override
    public boolean onContentLongClick(int position) {
        return onRowLongClick(position);
    }

    @Override
    public void onAvatarClick(String userId) {
        Intent roomDetailsIntent = new Intent(getActivity(), VectorMemberDetailsActivity.class);
        // in preview mode
        // the room is stored in a temporary store
        // so provide an handle to retrieve it
        if (null != getRoomPreviewData()) {
            roomDetailsIntent.putExtra(VectorMemberDetailsActivity.EXTRA_STORE_ID,
                    new Integer(Matrix.getInstance(getActivity()).addTmpStore(mEventTimeLine.getStore())));
        }

        roomDetailsIntent.putExtra(VectorMemberDetailsActivity.EXTRA_ROOM_ID, mRoom.getRoomId());
        roomDetailsIntent.putExtra(VectorMemberDetailsActivity.EXTRA_MEMBER_ID, userId);
        roomDetailsIntent.putExtra(VectorMemberDetailsActivity.EXTRA_MATRIX_ID, mSession.getCredentials().userId);
        getActivity().startActivityForResult(roomDetailsIntent, VectorRoomActivity.GET_MENTION_REQUEST_CODE);
    }

    @Override
    public boolean onAvatarLongClick(String userId) {
        if (getActivity() instanceof VectorRoomActivity) {
            RoomState state = mRoom.getLiveState();

            if (null != state) {
                String displayName = state.getMemberName(userId);
                if (!TextUtils.isEmpty(displayName)) {
                    ((VectorRoomActivity) getActivity()).insertUserDisplayenInTextEditor(displayName);
                }
            }
        }
        return true;
    }

    @Override
    public void onSenderNameClick(String userId, String displayName) {
        if (getActivity() instanceof VectorRoomActivity) {
            ((VectorRoomActivity) getActivity()).insertUserDisplayenInTextEditor(displayName);
        }
    }

    @Override
    public void onMediaDownloaded(int position) {
    }

    @Override
    public void onMoreReadReceiptClick(String eventId) {
        FragmentManager fm = getActivity().getSupportFragmentManager();

        VectorReadReceiptsDialogFragment fragment = (VectorReadReceiptsDialogFragment) fm
                .findFragmentByTag(TAG_FRAGMENT_RECEIPTS_DIALOG);
        if (fragment != null) {
            fragment.dismissAllowingStateLoss();
        }
        fragment = VectorReadReceiptsDialogFragment.newInstance(mSession, mRoom.getRoomId(), eventId);
        fragment.show(fm, TAG_FRAGMENT_RECEIPTS_DIALOG);
    }

    @Override
    public void onURLClick(Uri uri) {
        if (null != uri) {
            if (null != VectorUniversalLinkReceiver.parseUniversalLink(uri)) {
                // pop to the home activity
                Intent intent = new Intent(getActivity(), VectorHomeActivity.class);
                intent.setFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
                        | android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP);
                intent.putExtra(VectorHomeActivity.EXTRA_JUMP_TO_UNIVERSAL_LINK, uri);
                getActivity().startActivity(intent);
            } else {
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                intent.putExtra(Browser.EXTRA_APPLICATION_ID, getActivity().getPackageName());
                getActivity().startActivity(intent);
            }
        }
    }

    @Override
    public void onMatrixUserIdClick(final String userId) {

        showInitLoading();

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                CommonActivityUtils.goToOneToOneRoom(mSession, userId, getActivity(), new ApiCallback<Void>() {
                    @Override
                    public void onSuccess(Void info) {
                        // nothing to do here
                    }

                    private void onError(String errorMessage) {
                        hideInitLoading();
                        CommonActivityUtils.displayToast(getActivity(), errorMessage);
                    }

                    @Override
                    public void onNetworkError(Exception e) {
                        onError(e.getLocalizedMessage());
                    }

                    @Override
                    public void onMatrixError(MatrixError e) {
                        onError(e.getLocalizedMessage());
                    }

                    @Override
                    public void onUnexpectedError(Exception e) {
                        onError(e.getLocalizedMessage());
                    }
                });
            }
        });
    }

    @Override
    public void onRoomAliasClick(String roomAlias) {
        try {
            onURLClick(Uri.parse(VectorUtils.getPermalink(roomAlias, null)));
        } catch (Exception e) {
            Log.e(LOG_TAG, "onRoomAliasClick failed " + e.getLocalizedMessage());
        }
    }

    @Override
    public void onRoomIdClick(String roomId) {
        try {
            onURLClick(Uri.parse(VectorUtils.getPermalink(roomId, null)));
        } catch (Exception e) {
            Log.e(LOG_TAG, "onRoomIdClick failed " + e.getLocalizedMessage());
        }
    }

    @Override
    public void onMessageIdClick(String messageId) {
        try {
            onURLClick(Uri.parse(VectorUtils.getPermalink(mRoom.getRoomId(), messageId)));
        } catch (Exception e) {
            Log.e(LOG_TAG, "onRoomIdClick failed " + e.getLocalizedMessage());
        }
    }
}