Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Ahmedbadereldin/18485ae38456f4c1656a7ede2d541c7e to your computer and use it in GitHub Desktop.
Save Ahmedbadereldin/18485ae38456f4c1656a7ede2d541c7e to your computer and use it in GitHub Desktop.
package com.techzone.moshtapp.chating;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.volley.toolbox.JsonObjectRequest;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentChange;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FieldValue;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.ListenerRegistration;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.SetOptions;
import com.google.firebase.firestore.WriteBatch;
import com.techzone.moshtapp.Activity.User.MainActivity;
import com.techzone.moshtapp.Activity.salon.SalonMainActivity;
import com.techzone.moshtapp.Database.SessionCustomer;
import com.techzone.moshtapp.Database.SessionSaloon;
import com.techzone.moshtapp.Database.VolleySingleton;
import com.techzone.moshtapp.R;
import com.techzone.moshtapp.SplashActivity.SplashActivity;
import com.techzone.moshtapp.chating.model.Message;
import com.techzone.moshtapp.model.ContentSaloonProfile;
import com.techzone.moshtapp.model.ContentUserProfile;
import com.techzone.moshtapp.model.UserModel;
import com.techzone.moshtapp.notifications.MyFirebaseMessagingService;
import com.techzone.moshtapp.utiles.Constants;
import com.techzone.moshtapp.utiles.FamousFunction;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
public class ChatActivity extends AppCompatActivity {
private LinearLayout parent;
private RecyclerView rv;
private EditText messageTxt;
private LinearLayout messageLY;
private ImageView sendBtn;
private TextView title;
public static boolean isOpen = false;
public static String chatIdNotify = "";
boolean isNotify;
// ContentUserProfile user;
UserModel messageSendToUser;
UserModel myAccount;
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm", new Locale("en"));
private SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd", new Locale("en"));
private SimpleDateFormat dateFormatHour = new SimpleDateFormat("aa hh:mm", new Locale("en"));
private String roomID;
private String roomTitle;
private String isDone;
private String myUid, myName, myImage;
private String toUid;
private Map<String, UserModel> userList = new HashMap<>();
String TOPIC;
private ListenerRegistration listenerRegistration;
private FirebaseFirestore firestore = null;
private LinearLayoutManager linearLayoutManager;
private Integer userCount = 0;
private RecyclerViewAdapter mAdapter;
boolean isUser;
final private String FCM_API = "https://fcm.googleapis.com/fcm/send";
final private String serverKey = "key=" + "AAAAjlGQod0:APA91bHBqytFX7ns2_duEEJmJ3fdWBPCtt3vVSybIEXTnHwZkioAKbD9f1O84rfru_k7Gya0vImt9-Ll5MQmXH0oY46RaugxH-FbUrrFUyZkRCShBPunMMl-Ig6iFbDZB9FxyGPQilKe";
final private String contentType = "application/json";
View view_back;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
isOpen = true;
isUser = FamousFunction.sharedPrefrences.getTypeUser(this).equals("user");
toUid = getIntent().getStringExtra("toUid");
roomID = getIntent().getStringExtra(Constants.KEY_CHAT_ID);
chatIdNotify = roomID;
Log.d("roomID", "onCreate: " + roomID);
roomTitle = getIntent().getStringExtra(Constants.KEY_ROOM_TITILE);
isDone = getIntent().getStringExtra("isDone");
if (SessionCustomer.getInstanse().isUserLogIn()) {
ContentUserProfile contentUserProfile = SessionCustomer.getInstanse().getContentUserProfile();
myUid = contentUserProfile.getId() + "";
myName = contentUserProfile.getName();
myImage = contentUserProfile.getImage();
} else if (SessionSaloon.getInstanse().isSaloonLogIn()) {
ContentSaloonProfile contentSaloonProfile = SessionSaloon.getInstanse().getContentSaloonProfile();
myUid = contentSaloonProfile.getId() + "";
myName = contentSaloonProfile.getName();
myImage = contentSaloonProfile.getIdentity_pic();
}
firestore = VolleySingleton.fireStoreDB;
parent = findViewById(R.id.parent);
rv = findViewById(R.id.rv);
view_back = findViewById(R.id.view_back);
messageTxt = findViewById(R.id.messageTxt);
title = findViewById(R.id.title);
title.setText(roomTitle);
messageLY = findViewById(R.id.messageLY);
sendBtn = findViewById(R.id.sendBtn);
sendBtn.setOnClickListener(sendBtnClickListener);
rv.setHasFixedSize(true);
linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
linearLayoutManager.setStackFromEnd(true);
rv.setLayoutManager(linearLayoutManager);
setUpActivity();
}
private void setUpActivity() {
if (!"".equals(toUid) && toUid != null) { // find existing room for two user
findChatRoom(toUid);
} else if (!"".equals(roomID) && roomID != null) { // existing room (multi user)
setChatRoom(roomID);
}
if (roomID == null) { // new room for two user
getUserInfoFromServer(myUid);
getUserInfoFromServer(toUid);
userCount = 2;
}
rv.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
if (mAdapter != null & bottom < oldBottom) {
final int lastAdapterItem = mAdapter.getItemCount() - 1;
rv.post(() -> {
int recyclerViewPositionOffset = -1000000;
View bottomView = linearLayoutManager.findViewByPosition(lastAdapterItem);
if (bottomView != null) {
recyclerViewPositionOffset = 0 - bottomView.getHeight();
}
linearLayoutManager.scrollToPositionWithOffset(lastAdapterItem, recyclerViewPositionOffset);
});
}
});
view_back.setOnClickListener(v -> {
if (isDone.equals("yes")) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(Constants.KEY_NOTIFY_TYPE, MyFirebaseMessagingService.CHAT_LIST);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
super.onBackPressed();
}
});
}
void findChatRoom(final String toUid) {
firestore.collection("rooms").whereGreaterThanOrEqualTo("users." + myUid, 0).get()
.addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
return;
}
for (QueryDocumentSnapshot document : task.getResult()) {
Map<String, Long> users = (Map<String, Long>) document.get("users");
if (users.size() == 2 & users.get(toUid) != null) {
setChatRoom(document.getId());
break;
}
}
});
}
void setChatRoom(String rid) {
roomID = rid;
firestore.collection("rooms").document(roomID).get().addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
return;
}
DocumentSnapshot document = task.getResult();
Map<String, Long> users = (Map<String, Long>) document.get("users");
for (String key : users.keySet()) {
getUserInfoFromServer(key);
}
userCount = users.size();
//users.put(myUid, (long) 0);
//document.getReference().update("users", users);
});
}
void setUnread2Read() {
if (roomID == null) return;
firestore.collection("rooms").document(roomID).get().addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
return;
}
DocumentSnapshot document = task.getResult();
Map<String, Long> users = (Map<String, Long>) document.get("users");
users.put(myUid, (long) 0);
document.getReference().update("users", users);
});
}
void getUserInfoFromServer(String id) {
Log.d("getUserInfoFromServer", "getUserInfoFromServer: " + id + " " + firestore);
firestore.collection("users").document(id).get().addOnSuccessListener(documentSnapshot -> {
UserModel user = documentSnapshot.toObject(UserModel.class);
Log.d("getUserInfoFromServer", "getUserInfoFromServer: " + user);
userList.put(String.valueOf(user.getId()), user);
if (roomID != null & userCount == userList.size()) {
mAdapter = new RecyclerViewAdapter();
rv.setAdapter(mAdapter);
}
});
}
@Override
public void onBackPressed() {
if (isDone.equals("yes")) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(Constants.KEY_NOTIFY_TYPE, MyFirebaseMessagingService.CHAT_LIST);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
super.onBackPressed();
}
}
private void sendMessage(final String msg) {
sendBtn.setEnabled(false);
if (roomID == null) { // create chatting room for two user
roomID = firestore.collection("rooms").document().getId();
CreateChattingRoom(firestore.collection("rooms").document(roomID));
}
final Map<String, Object> messages = new HashMap<>();
messages.put("uid", myUid);
messages.put("photo", myImage);
messages.put("msg", msg);
messages.put("msgtype", "0");
messages.put("timestamp", FieldValue.serverTimestamp());
Map<String, Integer> delete = new HashMap<>();
for (String key : userList.keySet()) {
delete.put(key, 0);
}
messages.put("delete", delete);
final DocumentReference docRef = firestore.collection("rooms").document(roomID);
docRef.get().addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
return;
}
WriteBatch batch = firestore.batch();
// save last message
batch.set(docRef, messages, SetOptions.merge());
// save message
List<String> readUsers = new ArrayList();
readUsers.add(myUid);
messages.put("readUsers", readUsers);//new String[]{myUid} );
batch.set(docRef.collection("messages").document(), messages);
DocumentSnapshot document = task.getResult();
Map<String, Long> users = (Map<String, Long>) document.get("users");
for (String key : users.keySet()) {
if (!myUid.equals(key)) users.put(key, users.get(key) + 1);
}
for (String key : userList.keySet()) {
if (!myUid.equals(key)) {
messageSendToUser = userList.get(key);
Log.d("sendMessage", "sendMessage: " + messageSendToUser.getId());
if (isUser) {
TOPIC = "/topics/salon_" + messageSendToUser.getId(); //topic has to match what the receiver subscribed to
} else
TOPIC = "/topics/user_" + messageSendToUser.getId(); //topic has to match what the receiver subscribed to
JSONObject notification = new JSONObject();
JSONObject notifcationBody = new JSONObject();
try {
notifcationBody.put("title", myName);
notifcationBody.put("chatID", roomID);
notifcationBody.put("type", "chat");
notifcationBody.put("body", msg);
notification.put("to", TOPIC);
notification.put("notification", notifcationBody);
notification.put("data", notifcationBody);
} catch (JSONException e) {
Log.e("onCreate", "onCreate: " + e.getMessage());
}
sendNotification(notification);
}
}
document.getReference().update("users", users);
batch.commit().addOnCompleteListener(task1 -> {
if (task1.isSuccessful()) {
sendBtn.setEnabled(true);
}
});
});
}
public void CreateChattingRoom(final DocumentReference room) {
Map<String, Integer> users = new HashMap<>();
Map<String, Integer> delete = new HashMap<>();
String title = "";
for (String key : userList.keySet()) {
users.put(key, 0);
delete.put(key, 0);
}
Map<String, Object> data = new HashMap<>();
data.put("title", null);
data.put("users", users);
data.put("delete", delete);
room.set(data).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
mAdapter = new RecyclerViewAdapter();
rv.setAdapter(mAdapter);
}
});
}
Button.OnClickListener sendBtnClickListener = new View.OnClickListener() {
public void onClick(View view) {
String msg = messageTxt.getText().toString();
if (msg.trim().equals("")) {
messageTxt.setError("ادخل رسالتك هنا");
return;
}
sendMessage(msg);
messageTxt.setText("");
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (mAdapter != null) {
mAdapter.stopListening();
}
}
@Override
protected void onResume() {
super.onResume();
isOpen = true;
}
@Override
protected void onPause() {
super.onPause();
isOpen = false;
chatIdNotify = "";
}
// =======================================================================================
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<Message> messageList;
String beforeDay = null;
RecyclerViewAdapter() {
messageList = new ArrayList<>();
setUnread2Read();
startListening();
}
public void startListening() {
beforeDay = null;
messageList.clear();
CollectionReference roomRef = firestore.collection("rooms").document(roomID).collection("messages");
// my chatting room information
Query query = roomRef.orderBy("timestamp");
// Query query = roomRef.whereEqualTo("delete." + myUid, 0).orderBy("timestamp");
listenerRegistration = query.addSnapshotListener((documentSnapshots, e) -> {
if (e != null) {
return;
}
Message message;
for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
switch (change.getType()) {
case ADDED:
message = change.getDocument().toObject(Message.class);
if (message.getReadUsers().indexOf(myUid) == -1) {
message.getReadUsers().add(myUid);
change.getDocument().getReference().update("readUsers", message.getReadUsers());
}
if (message.getDelete().get(myUid) == 0) {
messageList.add(message);
notifyItemInserted(messageList.size() - 1);
}
// notifyItemInserted(change.getNewIndex() );
break;
case MODIFIED://time
message = change.getDocument().toObject(Message.class);
if (message.getDelete().get(myUid) == 0) {
messageList.set(messageList.size() - 1, message);
notifyItemChanged(messageList.size() - 1);
}
// notifyItemChanged(change.getOldIndex());
break;
case REMOVED:
messageList.remove(messageList.size() - 1);
notifyItemRemoved(messageList.size() - 1);
break;
}
}
rv.scrollToPosition(messageList.size() - 1);
});
}
public void stopListening() {
if (listenerRegistration != null) {
listenerRegistration.remove();
listenerRegistration = null;
}
messageList.clear();
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
Message message = messageList.get(position);
if (myUid.equals(message.getUid())) {
return R.layout.item_chatmsg_right;
} else {
return R.layout.item_chatmsg_left;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
return new MessageViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
final MessageViewHolder messageViewHolder = (MessageViewHolder) holder;
final Message message = messageList.get(position);
if ("0".equals(message.getMsgtype())) { // text message
messageViewHolder.msg_item.setText(message.getMsg());
}
if (!myUid.equals(message.getUid())) {
UserModel user = userList.get(message.getUid());
// messageViewHolder.msg_name.setText(user.getName());
}
messageViewHolder.divider.setVisibility(View.INVISIBLE);
messageViewHolder.divider.getLayoutParams().height = 0;
messageViewHolder.timestamp.setText("");
if (message.getTimestamp() == null) {
return;
}
String day = dateFormatDay.format(message.getTimestamp());
String timestamp = dateFormatHour.format(message.getTimestamp());
messageViewHolder.timestamp.setText(timestamp);
// Log.d("onBindViewHolder", "onBindViewHolder: " + message.getTimestamp());
Log.d("onBindViewHolderAA", "onBindViewHolder: " + position);
if (position == 0) {
messageViewHolder.divider_date.setText(day);
messageViewHolder.divider.setVisibility(View.VISIBLE);
messageViewHolder.divider.getLayoutParams().height = 60;
} else {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Date d = cal.getTime();
String beforeDay;
Message beforeMsg = messageList.get(position - 1);
// todo import --------------------
if (beforeMsg.getTimestamp() == null) {
beforeDay = dateFormatDay.format(d);
} else {
beforeDay = dateFormatDay.format(beforeMsg.getTimestamp());
}
if (!day.equals(beforeDay)) {
messageViewHolder.divider_date.setText(day);
messageViewHolder.divider.setVisibility(View.VISIBLE);
messageViewHolder.divider.getLayoutParams().height = 60;
}
}
}
void setReadCounter(Message message, final TextView textView) {
int cnt = userCount - message.getReadUsers().size();
if (cnt > 0) {
textView.setVisibility(View.INVISIBLE);
textView.setText(String.valueOf(cnt));
} else {
textView.setVisibility(View.INVISIBLE);
}
}
@Override
public int getItemCount() {
return messageList.size();
}
}
private class MessageViewHolder extends RecyclerView.ViewHolder {
ImageView user_photo;
TextView msg_item;
// public TextView msg_name;
TextView timestamp;
// public TextView read_counter;
LinearLayout divider;
TextView divider_date;
public String filename;
public String realname;
public MessageViewHolder(View view) {
super(view);
user_photo = view.findViewById(R.id.user_photo);
msg_item = view.findViewById(R.id.msg_item);
timestamp = view.findViewById(R.id.timestamp);
divider = view.findViewById(R.id.divider);
divider_date = view.findViewById(R.id.divider_date);
}
}
private void sendNotification(JSONObject notification) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
response -> {
Log.i("onResponse", "onResponse: " + response.toString());
},
error -> {
Log.i("onErrorResponse", "onErrorResponse: Didn't work");
}) {
@Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<>();
params.put("Authorization", serverKey);
params.put("Content-Type", contentType);
return params;
}
};
VolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
// =======================================================================================
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment