Created
December 5, 2019 07:49
-
-
Save Ahmedbadereldin/18485ae38456f4c1656a7ede2d541c7e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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