geofot96/StudyBuddy

View on GitHub
app/src/main/java/ch/epfl/sweng/studdybuddy/activities/ChatActivity.java

Summary

Maintainability
A
0 mins
Test Coverage
package ch.epfl.sweng.studdybuddy.activities;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.firebase.ui.database.FirebaseListAdapter;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import ch.epfl.sweng.studdybuddy.R;
import ch.epfl.sweng.studdybuddy.core.User;
import ch.epfl.sweng.studdybuddy.firebase.FirebaseReference;
import ch.epfl.sweng.studdybuddy.firebase.MetaGroup;
import ch.epfl.sweng.studdybuddy.services.chat.ChatMessage;
import ch.epfl.sweng.studdybuddy.services.notifications.MyFirebaseMessaging;
import ch.epfl.sweng.studdybuddy.util.Messages;

/**
 * An activity showing text messages and photos sent between the members of a group
 */
public class ChatActivity extends AppCompatActivity{
    String groupID;
    public FirebaseReference ref;
    private StorageReference storageRef;
    private Button addImage, cameraButon;
    private String downloadUri;
    protected static final int PICK_IMAGE_REQUEST = 1;
    protected static final int OPEN_CAMERA_REQUEST = 42;
    private FloatingActionButton fab;

    protected DatabaseReference mNotificationsRef;
    private static List<User> users = new ArrayList<>();
    protected FirebaseUser auth;

    /**
     * OnCreate method setting up all the graphical components
     */
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);
        this.ref = initRef();
        storageRef = FirebaseStorage.getInstance().getReference();

        Bundle extras = getIntent().getExtras();

        if (extras != null) {
            groupID = extras.getString(Messages.groupID);
        } else {
            Toast.makeText(this,
                    "Group not found in database",
                    Toast.LENGTH_SHORT).show();
            finish();
        }

        MetaGroup mGp = new MetaGroup();
        mGp.getGroupUsers(groupID, users);

        initializations();
    }
    /**
     * A helper function that sets up part of the graphical components
     */
    private void initializations() {
        downloadUri = "";
        displayChatMessages();
        fab = (FloatingActionButton) findViewById(R.id.fab);
        addImage = (Button) findViewById(R.id.gallery);
        addImage.setOnClickListener(getGalleryImage());
        cameraButon = (Button) findViewById(R.id.camera);
        cameraButon.setOnClickListener(getCameraListener());
        //check if camera permission is granted and when it isn't ask for it]
        askForCameraPermission();
        fab.setOnClickListener(getFabListener());
        initDatabaseReference();
        initAuthenticatedUser();
    }

    protected void initAuthenticatedUser() {auth = FirebaseAuth.getInstance().getCurrentUser();}

    protected void initDatabaseReference() {mNotificationsRef = FirebaseDatabase.getInstance().getReference("notifications");}

    @Override
    protected void onStart() {
        super.onStart();
        //we avoid receiving notifications from people we are currently chatting with
        MyFirebaseMessaging.setCurrentGroupID(groupID);
    }

    @Override
    protected void onStop(){
        super.onStop();
        //once we don't see the chat box anymore, we tell to myFirebaseMessaging to send us
        //the further notification from this chat box
        MyFirebaseMessaging.setCurrentGroupID(MyFirebaseMessaging.NO_GROUP);
    }


    /**
     * Check if permissions for using the camera are granted and if not prompt a message to ask the user
     */
    private void askForCameraPermission() {
        if (ContextCompat.checkSelfPermission(ChatActivity.this.getApplicationContext(),
                Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(ChatActivity.this,
                    new String[]{Manifest.permission.CAMERA},
                    1);
        }
    }
    /**
     * Start an intent demanding for the system gallery- style photo picker to be started
     */
    @NonNull
    protected View.OnClickListener getGalleryImage() {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent galleryIntent = new Intent();
                galleryIntent.setType("image/*");
                galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

                startActivityForResult(Intent.createChooser(galleryIntent, "SELECT IMAGE"), PICK_IMAGE_REQUEST);
            }
        };
    }
    /**
     * Start an intent demanding for the system camera capture to be started
     */
    @NonNull
    protected View.OnClickListener getCameraListener() {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, OPEN_CAMERA_REQUEST);
            }
        };
    }

    /**
     * Initiate the retrieval of filepath of the selected image
     * @param requestCode The code to be transmitted through an intent
     * @param resultCode resulting code of the operation
     * @param data intent to be started
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && data != null) {
            initiatePhotoRequest(requestCode, data);
        }
    }
    /**
     * Decide wether the user asked to pick an existing photo or capture a new one
     * @param requestCode the code contained within the received intent
     * @param data the intent captured
     */
    private void initiatePhotoRequest(int requestCode, Intent data) {
        if (requestCode == PICK_IMAGE_REQUEST) {
            ChatUtils.uploadImageFromGallery(getFilePath(data), storageRef).addOnCompleteListener(getOnCompleteListener());
        }
        if (requestCode == OPEN_CAMERA_REQUEST) {
            ChatUtils.openCamera(data, getApplicationContext()).addOnSuccessListener(getOnSuccessListener());
        }
    }

    /**
     * Method to be mocked at DummyChatChatActivity.
     *
     * @param data Intent containing the data
     * @return Returns the Filepath of a Uri contained within an intent
     */

    protected Uri getFilePath(Intent data) {
        return data.getData();
    }

    /**
     *
     * @return Upload the image once the selected or captured photo has been loaded
     */
    @NonNull
    private OnSuccessListener<UploadTask.TaskSnapshot> getOnSuccessListener() {
        return new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                Task<Uri> urlTask = taskSnapshot.getStorage().getDownloadUrl();
                while (!urlTask.isSuccessful()) ;
                setDownloadUri(urlTask.getResult().toString());
                //mProgress.dismiss();

                fab.performClick();
            }
        };
    }
    /**
     * Method to be mocked at DummyChatChatActivity.
     * @return the firebaseReference
     */
    public FirebaseReference initRef() {
        return new FirebaseReference();
    }

    /**
     * Notify user if the uploading process failed or succeeded
     * @return returns a OnCompleteListener with the specified feature
     */
    @NonNull
    private OnCompleteListener<Uri> getOnCompleteListener() {
        return new OnCompleteListener<Uri>() {
            @Override
            public void onComplete(@NonNull Task<Uri> task) {
                if (task.isSuccessful()) {
                    setDownloadUri(task.getResult().toString());
                    fab.performClick();
                    Toast.makeText(ChatActivity.this, "Uploaded ", Toast.LENGTH_SHORT).show();

                } else {
                    Toast.makeText(ChatActivity.this, "Failed Uploading", Toast.LENGTH_LONG).show();
                }
            }
        };
    }
    /**
     * The listener assigned to the FAB that sends the message
     * @return The aforementioned listener
     */
    @NonNull
    protected View.OnClickListener getFabListener() {
        EditText input = (EditText) findViewById(R.id.input);
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fabListener(input, ref, groupID, downloadUri);
            }
        };
    }

    /**
     * Setter for the downloadUri
     * @param downloadUri the new downloadUri to be set
     */
    public void setDownloadUri(String downloadUri) {
        this.downloadUri = downloadUri;
    }

    /**
     * Initializes the pushing to firebase procedure and clears the used fields
     * @param inputText InputText containing the message to be sent
     * @param reference the FirebaseReference
     * @param groupsID the id of the current group related to this chat
     * @param downloadURI the uri of the uploaded image
     * @return //TODO
     */
    public int fabListener(EditText inputText, FirebaseReference reference, String groupsID, String downloadURI) {
        if (inputText.getText().toString().trim().length() > 0 || !downloadURI.isEmpty()) {
            pushMessage(inputText, reference, groupsID, downloadURI);
            inputText.setText("");
            setDownloadUri("");
            displayChatMessages();
        }
        return 0;//TODO also change the return comment
    }

    protected void pushMessage(EditText inputText, FirebaseReference reference, String groupsID, String downloadURI) {
        if(auth != null) {
            ChatUtils.pushToFirebase(reference, groupsID, inputText.getText().toString(), downloadURI)
                    .addOnSuccessListener(ChatUtils.getOnSuccessListener(mNotificationsRef, auth, groupsID, users));
        }
    }

    /**
     * Updates the list of messages visible on screen with the information retrieved from Firebase
     */
    public void displayChatMessages() {
        ListView listOfMessages = (ListView) findViewById(R.id.list_of_messages);

        FirebaseListAdapter<ChatMessage> adapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class,
                R.layout.message,
                FirebaseDatabase.getInstance().getReference().child(Messages.FirebaseNode.CHAT).child(groupID)) {
            @Override
            protected void populateView(View v, ChatMessage model, int position) {
                popViewBody(v, model);
            }

        };
        listOfMessages.setAdapter(adapter);
    }

    public int popViewBody(View v, ChatMessage model) {
        TextView messageUser = (TextView) v.findViewById(R.id.message_user);
        messageUser.setText(model.getMessageUser());
        TextView messageTime = (TextView) v.findViewById(R.id.message_time);
        messageTime.setText(getDate(model));
        TextView messageText = (TextView) v.findViewById(R.id.message_text);
        messageText.setText(model.getMessageText());
        ImageView image = (ImageView) v.findViewById(R.id.imgViewGall);
        String modelUri = model.getImageUri();
        if (modelUri != null && !modelUri.isEmpty()) {
            //Put the image in the chat
            Glide.with(ChatActivity.this).
                    load(modelUri)
                    .apply(new RequestOptions().override(500, 700)).
                    into(image);
        } else {
            image.setImageResource(android.R.color.transparent);
        }
        return 0;
    }

    protected CharSequence getDate(ChatMessage model) {
        return DateFormat.format("dd-MM (HH:mm)", model.getMessageTime());
    }
}