From 9375fcb717983a969b2bda4001e3dcf7815a960a Mon Sep 17 00:00:00 2001 From: magonyfur Date: Thu, 22 Dec 2022 09:43:28 +0100 Subject: [PATCH] first commit --- README.md | 35 ++ app/.gitignore | 1 + app/build.gradle | 50 +++ app/proguard-rules.pro | 21 ++ .../chatapp/ExampleInstrumentedTest.java | 26 ++ app/src/main/AndroidManifest.xml | 59 ++++ app/src/main/assets/fonts/myriad.ttf | Bin 0 -> 29680 bytes app/src/main/assets/fonts/myriadregular.ttf | Bin 0 -> 94884 bytes app/src/main/ic_launcher-web.png | Bin 0 -> 12683 bytes .../chatapp/Adapter/MessageAdapter.java | 124 +++++++ .../saharsh/chatapp/Adapter/OnItemClick.java | 7 + .../saharsh/chatapp/Adapter/UserAdapter.java | 176 ++++++++++ .../com/saharsh/chatapp/BaseActivity.java | 110 ++++++ .../saharsh/chatapp/Fragments/APIService.java | 21 ++ .../chatapp/Fragments/ChatsFragment.java | 157 +++++++++ .../chatapp/Fragments/ProfileFragment.java | 253 +++++++++++++ .../chatapp/Fragments/UsersFragment.java | 176 ++++++++++ .../com/saharsh/chatapp/LoginActivity.java | 106 ++++++ .../com/saharsh/chatapp/MainActivity.java | 251 +++++++++++++ .../com/saharsh/chatapp/MessageActivity.java | 332 ++++++++++++++++++ .../java/com/saharsh/chatapp/Model/Chat.java | 61 ++++ .../com/saharsh/chatapp/Model/Chatlist.java | 20 ++ .../java/com/saharsh/chatapp/Model/User.java | 73 ++++ .../saharsh/chatapp/Notifications/Client.java | 19 + .../saharsh/chatapp/Notifications/Data.java | 60 ++++ .../Notifications/MyFirebaseIdService.java | 30 ++ .../Notifications/MyFirebaseMessaging.java | 108 ++++++ .../chatapp/Notifications/MyResponse.java | 6 + .../Notifications/OreoNotification.java | 60 ++++ .../saharsh/chatapp/Notifications/Sender.java | 11 + .../saharsh/chatapp/Notifications/Token.java | 20 ++ .../com/saharsh/chatapp/RegisterActivity.java | 131 +++++++ .../chatapp/ResetPasswordActivity.java | 76 ++++ .../com/saharsh/chatapp/StartActivity.java | 69 ++++ .../main/java/com/saharsh/chatapp/Utils.java | 46 +++ .../saharsh/chatapp/ViewProfileActivity.java | 87 +++++ .../main/res/drawable-hdpi/ic_action_name.png | Bin 0 -> 651 bytes .../main/res/drawable-mdpi/ic_action_name.png | Bin 0 -> 451 bytes .../main/res/drawable-mdpi/rounded_dialog.xml | 8 + .../drawable-v24/ic_launcher_foreground.xml | 34 ++ .../res/drawable-xhdpi/ic_action_name.png | Bin 0 -> 641 bytes .../res/drawable-xxhdpi/ic_action_name.png | Bin 0 -> 1241 bytes app/src/main/res/drawable/background_left.xml | 107 ++++++ .../main/res/drawable/background_right.xml | 108 ++++++ app/src/main/res/drawable/button_bg.xml | 7 + app/src/main/res/drawable/edittext_bg.xml | 12 + app/src/main/res/drawable/es_image.xml | 47 +++ app/src/main/res/drawable/ic_arrow_img.xml | 21 ++ .../main/res/drawable/ic_chevron_right.xml | 13 + .../main/res/drawable/ic_cool_background.xml | 58 +++ app/src/main/res/drawable/ic_edit.xml | 5 + .../main/res/drawable/ic_forgot_password.xml | 137 ++++++++ .../res/drawable/ic_launcher_background.xml | 170 +++++++++ app/src/main/res/drawable/ic_lock.xml | 7 + app/src/main/res/drawable/ic_login.xml | 13 + app/src/main/res/drawable/ic_login_vector.xml | 115 ++++++ app/src/main/res/drawable/ic_next.xml | 4 + app/src/main/res/drawable/ic_picture.xml | 6 + app/src/main/res/drawable/ic_plus.xml | 5 + app/src/main/res/drawable/ic_send.xml | 21 ++ .../main/res/drawable/ic_signup_vector.xml | 177 ++++++++++ .../main/res/drawable/ic_vector_chatapp.xml | 192 ++++++++++ app/src/main/res/drawable/profile_img.xml | 17 + .../main/res/drawable/rounded_edittext.xml | 10 + app/src/main/res/drawable/search_bg.xml | 5 + app/src/main/res/layout/activity_login.xml | 100 ++++++ app/src/main/res/layout/activity_main.xml | 59 ++++ app/src/main/res/layout/activity_message.xml | 85 +++++ app/src/main/res/layout/activity_register.xml | 99 ++++++ .../res/layout/activity_reset_password.xml | 63 ++++ app/src/main/res/layout/activity_start.xml | 58 +++ .../main/res/layout/activity_view_profile.xml | 97 +++++ app/src/main/res/layout/bar_layout.xml | 11 + app/src/main/res/layout/chat_item_left.xml | 52 +++ app/src/main/res/layout/chat_item_right.xml | 60 ++++ app/src/main/res/layout/empty_state.xml | 64 ++++ app/src/main/res/layout/fragment_chats.xml | 19 + app/src/main/res/layout/fragment_profile.xml | 142 ++++++++ app/src/main/res/layout/fragment_users.xml | 37 ++ app/src/main/res/layout/progressdialog.xml | 17 + app/src/main/res/layout/user_item.xml | 95 +++++ app/src/main/res/menu/menu.xml | 10 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1136 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1000 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 2892 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 793 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 702 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 1796 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 1679 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 1512 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4302 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 2705 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 2427 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 6910 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 3883 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 3476 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 10051 bytes app/src/main/res/values/colors.xml | 12 + app/src/main/res/values/dimens.xml | 15 + .../res/values/ic_launcher_background.xml | 4 + app/src/main/res/values/strings.xml | 6 + app/src/main/res/values/styles.xml | 51 +++ .../com/saharsh/chatapp/ExampleUnitTest.java | 17 + build.gradle | 28 ++ gradle.properties | 13 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 +++++++++ gradlew.bat | 84 +++++ settings.gradle | 1 + 112 files changed, 5568 insertions(+) create mode 100644 README.md create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/saharsh/chatapp/ExampleInstrumentedTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/assets/fonts/myriad.ttf create mode 100644 app/src/main/assets/fonts/myriadregular.ttf create mode 100644 app/src/main/ic_launcher-web.png create mode 100644 app/src/main/java/com/saharsh/chatapp/Adapter/MessageAdapter.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Adapter/OnItemClick.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Adapter/UserAdapter.java create mode 100644 app/src/main/java/com/saharsh/chatapp/BaseActivity.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Fragments/APIService.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Fragments/ChatsFragment.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Fragments/ProfileFragment.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Fragments/UsersFragment.java create mode 100644 app/src/main/java/com/saharsh/chatapp/LoginActivity.java create mode 100644 app/src/main/java/com/saharsh/chatapp/MainActivity.java create mode 100644 app/src/main/java/com/saharsh/chatapp/MessageActivity.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Model/Chat.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Model/Chatlist.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Model/User.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/Client.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/Data.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseIdService.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseMessaging.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/MyResponse.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/OreoNotification.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/Sender.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Notifications/Token.java create mode 100644 app/src/main/java/com/saharsh/chatapp/RegisterActivity.java create mode 100644 app/src/main/java/com/saharsh/chatapp/ResetPasswordActivity.java create mode 100644 app/src/main/java/com/saharsh/chatapp/StartActivity.java create mode 100644 app/src/main/java/com/saharsh/chatapp/Utils.java create mode 100644 app/src/main/java/com/saharsh/chatapp/ViewProfileActivity.java create mode 100644 app/src/main/res/drawable-hdpi/ic_action_name.png create mode 100644 app/src/main/res/drawable-mdpi/ic_action_name.png create mode 100644 app/src/main/res/drawable-mdpi/rounded_dialog.xml create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_name.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_name.png create mode 100644 app/src/main/res/drawable/background_left.xml create mode 100644 app/src/main/res/drawable/background_right.xml create mode 100644 app/src/main/res/drawable/button_bg.xml create mode 100644 app/src/main/res/drawable/edittext_bg.xml create mode 100644 app/src/main/res/drawable/es_image.xml create mode 100644 app/src/main/res/drawable/ic_arrow_img.xml create mode 100644 app/src/main/res/drawable/ic_chevron_right.xml create mode 100644 app/src/main/res/drawable/ic_cool_background.xml create mode 100644 app/src/main/res/drawable/ic_edit.xml create mode 100644 app/src/main/res/drawable/ic_forgot_password.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/ic_lock.xml create mode 100644 app/src/main/res/drawable/ic_login.xml create mode 100644 app/src/main/res/drawable/ic_login_vector.xml create mode 100644 app/src/main/res/drawable/ic_next.xml create mode 100644 app/src/main/res/drawable/ic_picture.xml create mode 100644 app/src/main/res/drawable/ic_plus.xml create mode 100644 app/src/main/res/drawable/ic_send.xml create mode 100644 app/src/main/res/drawable/ic_signup_vector.xml create mode 100644 app/src/main/res/drawable/ic_vector_chatapp.xml create mode 100644 app/src/main/res/drawable/profile_img.xml create mode 100644 app/src/main/res/drawable/rounded_edittext.xml create mode 100644 app/src/main/res/drawable/search_bg.xml create mode 100644 app/src/main/res/layout/activity_login.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/activity_message.xml create mode 100644 app/src/main/res/layout/activity_register.xml create mode 100644 app/src/main/res/layout/activity_reset_password.xml create mode 100644 app/src/main/res/layout/activity_start.xml create mode 100644 app/src/main/res/layout/activity_view_profile.xml create mode 100644 app/src/main/res/layout/bar_layout.xml create mode 100644 app/src/main/res/layout/chat_item_left.xml create mode 100644 app/src/main/res/layout/chat_item_right.xml create mode 100644 app/src/main/res/layout/empty_state.xml create mode 100644 app/src/main/res/layout/fragment_chats.xml create mode 100644 app/src/main/res/layout/fragment_profile.xml create mode 100644 app/src/main/res/layout/fragment_users.xml create mode 100644 app/src/main/res/layout/progressdialog.xml create mode 100644 app/src/main/res/layout/user_item.xml create mode 100644 app/src/main/res/menu/menu.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/ic_launcher_background.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/test/java/com/saharsh/chatapp/ExampleUnitTest.java create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/README.md b/README.md new file mode 100644 index 0000000..7a14dc0 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ + +# Messenger # + +If you want a APK then create an issue, i'll send the link.. +
ChatApp is a real time one to one chat application with Push Notifications made using Firebase... + +Add yours google-services.json +
Change Authorization:key with your key from firebase project + +
Implementation Guide +
1 - Project +
1 - Open the Project in your android studio; +
2 - *IMPORTANT* Change the Package Name. (https://stackoverflow.com/questions/16804093/android-studio-rename-package) + +
2 - Firebase Panel +
- Create Firebase Project (https://console.firebase.google.com/); +
- Import the file google-service.json into your project +
- Connect to firebase console authentication and database from your IDE +
- in firebase Storage Rules, change value of "allow read, write:" from "if request.auth != null" to "if true;" +
- For sending notification, paste your Firebase project key into your project APIService.java +
- When you change database settings, you likely will need to uninstall and reinstall apps to avoid app crashes due to app caches. + +Check out the design... +# Welcome, Login, Signup, Forgot Password + + +# Chats, Users, Profile Screens + + +# Chat Screen, Friend Profile, Logout Menu + + + + + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..4c00904 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,50 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "com.saharsh.chatapp" + minSdkVersion 16 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.2' + + //libraries we need for now + implementation 'com.android.support:support-v4:27.1.1' + implementation 'com.android.support:design:27.1.1' + implementation 'com.google.firebase:firebase-auth:16.0.2' + implementation 'com.google.firebase:firebase-database:16.0.1' + implementation 'com.google.firebase:firebase-core:16.0.1' + //add this + implementation 'com.google.firebase:firebase-storage:16.0.1' + implementation 'com.android.support:cardview-v7:27.1.1' + implementation 'com.rengwuxian.materialedittext:library:2.1.4' + //add this library and this + implementation 'de.hdodenhof:circleimageview:2.2.0' + implementation 'com.github.bumptech.glide:glide:4.8.0' + + //add these libraries + implementation 'com.squareup.retrofit2:retrofit:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.3.0' + implementation 'com.google.firebase:firebase-messaging:17.3.1' + + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} + +apply plugin: 'com.google.gms.google-services' diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/saharsh/chatapp/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/saharsh/chatapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..9b5ef8d --- /dev/null +++ b/app/src/androidTest/java/com/saharsh/chatapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.saharsh.chatapp; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.koddev.chatapp", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..040fc5d --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/fonts/myriad.ttf b/app/src/main/assets/fonts/myriad.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ff3bddd77ca0e9d72b3b4afedad6fe8484c7828f GIT binary patch literal 29680 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 literal 0 HcmV?d00001 diff --git a/app/src/main/assets/fonts/myriadregular.ttf b/app/src/main/assets/fonts/myriadregular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..57a953b54a4b34cdd4150d068fd987476f2ed37e GIT binary patch literal 94884 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�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 { + + public static final int MSG_TYPE_LEFT = 0; + public static final int MSG_TYPE_RIGHT = 1; + Typeface MR,MRR; + + + private Context mContext; + private List mChat; + private String imageurl; + + FirebaseUser fuser; + + public MessageAdapter(Context mContext, List mChat, String imageurl){ + this.mChat = mChat; + this.mContext = mContext; + this.imageurl = imageurl; + + MRR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriad.ttf"); + + } + + @NonNull + @Override + public MessageAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == MSG_TYPE_RIGHT) { + View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false); + return new MessageAdapter.ViewHolder(view); + } else { + View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false); + return new MessageAdapter.ViewHolder(view); + } + } + + @Override + public void onBindViewHolder(@NonNull MessageAdapter.ViewHolder holder, int position) { + + Chat chat = mChat.get(position); + holder.show_message.setTypeface(MRR); + holder.txt_seen.setTypeface(MRR); + + holder.show_message.setText(chat.getMessage()); + if(chat.getTime()!=null && !chat.getTime().trim().equals("")) { + holder.time_tv.setText(holder.convertTime(chat.getTime())); + } + + if (imageurl.equals("default")){ + holder.profile_image.setImageResource(R.drawable.profile_img); + } else { + Glide.with(mContext).load(imageurl).into(holder.profile_image); + } + + if (position == mChat.size()-1){ + if (chat.isIsseen()){ + holder.txt_seen.setText("Seen"); + } else { + holder.txt_seen.setText("Delivered"); + } + } else { + holder.txt_seen.setVisibility(View.GONE); + } + + } + + @Override + public int getItemCount() { + return mChat.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder{ + + public TextView show_message; + public ImageView profile_image; + public TextView txt_seen; + public TextView time_tv; + public ViewHolder(View itemView) { + super(itemView); + + show_message = itemView.findViewById(R.id.show_message); + profile_image = itemView.findViewById(R.id.profile_image); + txt_seen = itemView.findViewById(R.id.txt_seen); + time_tv = itemView.findViewById(R.id.time_tv); + } + + public String convertTime(String time){ + SimpleDateFormat formatter = new SimpleDateFormat("h:mm a"); + String dateString = formatter.format(new Date(Long.parseLong(time))); + return dateString; + } + } + + @Override + public int getItemViewType(int position) { + fuser = FirebaseAuth.getInstance().getCurrentUser(); + if (mChat.get(position).getSender().equals(fuser.getUid())){ + return MSG_TYPE_RIGHT; + } else { + return MSG_TYPE_LEFT; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/saharsh/chatapp/Adapter/OnItemClick.java b/app/src/main/java/com/saharsh/chatapp/Adapter/OnItemClick.java new file mode 100644 index 0000000..e0aa8c4 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Adapter/OnItemClick.java @@ -0,0 +1,7 @@ +package com.saharsh.chatapp.Adapter; + +import android.view.View; + +public interface OnItemClick { + public void onItemCLick(String uid, View view); +} diff --git a/app/src/main/java/com/saharsh/chatapp/Adapter/UserAdapter.java b/app/src/main/java/com/saharsh/chatapp/Adapter/UserAdapter.java new file mode 100644 index 0000000..2a6c031 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Adapter/UserAdapter.java @@ -0,0 +1,176 @@ +package com.saharsh.chatapp.Adapter; + +import android.app.FragmentTransaction; +import android.content.Context; +import android.content.Intent; +import android.graphics.Typeface; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.MainActivity; +import com.saharsh.chatapp.MessageActivity; +import com.saharsh.chatapp.Model.Chat; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.R; +import com.saharsh.chatapp.ViewProfileActivity; + +import java.util.List; + +public class UserAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mUsers; + private boolean ischat; + private OnItemClick onItemClick; + + Typeface MR,MRR; + String theLastMessage; + + public UserAdapter(Context mContext, OnItemClick onItemClick, List mUsers, boolean ischat){ + this.onItemClick = onItemClick; + this.mUsers = mUsers; + this.mContext = mContext; + this.ischat = ischat; + + if(mContext!=null) { + MRR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriad.ttf"); + } + + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.user_item, parent, false); + return new UserAdapter.ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + + final User user = mUsers.get(position); + holder.username.setTypeface(MR); + holder.last_msg.setTypeface(MRR); + + holder.username.setText(user.getUsername()); + if (user.getImageURL().equals("default")){ + holder.profile_image.setImageResource(R.drawable.profile_img); + } else { + Glide.with(mContext).load(user.getImageURL()).into(holder.profile_image); + } + + if (ischat){ + lastMessage(user.getId(), holder.last_msg); + } else { + holder.last_msg.setVisibility(View.GONE); + } + + if (ischat){ + if (user.getStatus().equals("online")){ + holder.img_on.setVisibility(View.VISIBLE); + holder.img_off.setVisibility(View.GONE); + } else { + holder.img_on.setVisibility(View.GONE); + holder.img_off.setVisibility(View.GONE); + } + } else { + holder.img_on.setVisibility(View.GONE); + holder.img_off.setVisibility(View.GONE); + } + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MessageActivity.class); + intent.putExtra("userid", user.getId()); + mContext.startActivity(intent); + } + }); + + + holder.profile_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onItemClick.onItemCLick(user.getId(),view); + } + }); + } + + @Override + public int getItemCount() { + return mUsers.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder{ + + public TextView username; + public ImageView profile_image; + private ImageView img_on; + private ImageView img_off; + private TextView last_msg; + + public ViewHolder(View itemView) { + super(itemView); + + username = itemView.findViewById(R.id.username); + profile_image = itemView.findViewById(R.id.profile_image); + img_on = itemView.findViewById(R.id.img_on); + img_off = itemView.findViewById(R.id.img_off); + last_msg = itemView.findViewById(R.id.last_msg); + } + } + + //check for last message + private void lastMessage(final String userid, final TextView last_msg){ + theLastMessage = "default"; + final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chats"); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (firebaseUser != null && chat != null) { + if (chat.getReceiver().equals(firebaseUser.getUid()) && chat.getSender().equals(userid) || + chat.getReceiver().equals(userid) && chat.getSender().equals(firebaseUser.getUid())) { + theLastMessage = chat.getMessage(); + } + } + } + + switch (theLastMessage){ + case "default": + last_msg.setText("No Message"); + break; + + default: + last_msg.setText(theLastMessage); + break; + } + + theLastMessage = "default"; + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/BaseActivity.java b/app/src/main/java/com/saharsh/chatapp/BaseActivity.java new file mode 100644 index 0000000..30c1185 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/BaseActivity.java @@ -0,0 +1,110 @@ +package com.saharsh.chatapp; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.view.Window; +import android.widget.Toast; + +public class BaseActivity extends AppCompatActivity{ + + public final String TAG = this.getClass().getSimpleName(); + private ProgressDialog progressDialog; + public Dialog dialog; +// LottieAnimationView lottieAnimationView; + + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + dialog = new Dialog(this, R.style.DimDisabled); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setCancelable(false); + + + } + + public void showLoader(String msg) { + try { + dialog.show(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void showLoader() { + try { + dialog.show(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void hideLoader() { + if (dialog != null) { + try { + dialog.dismiss(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + + public void showToast(String msg) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + + public void showErrorState() { + + } + + public void showEmptyState() { + + } + + + + + + +// public void showSnackbar(String msg){ +// Snackbar snackbar = Snackbar +// .make(getCurrentFocus(), "Try again!", Snackbar.LENGTH_LONG) +// .setAction("RETRY", new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// } +// }); +// snackbar.setActionTextColor(getResources().getColor(R.color.outreach_background_color)); +// View sbView = snackbar.getView(); +// TextView textView = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text); +// textView.setTextColor(Color.YELLOW); +// snackbar.show(); +// } + + public void showAlert(String title, String msg) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(title); + builder.setMessage(msg); + builder.setCancelable(false); + builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.dismiss(); + finish(); + } + }); + AlertDialog alertDialog = builder.create(); + alertDialog.setTitle(title); + alertDialog.show(); + } + + +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/APIService.java b/app/src/main/java/com/saharsh/chatapp/Fragments/APIService.java new file mode 100644 index 0000000..9181d7e --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/APIService.java @@ -0,0 +1,21 @@ +package com.saharsh.chatapp.Fragments; + +import com.saharsh.chatapp.Notifications.MyResponse; +import com.saharsh.chatapp.Notifications.Sender; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.Headers; +import retrofit2.http.POST; + +public interface APIService { + @Headers( + { + "Content-Type:application/json", + "Authorization:key=AAAAxNjVIwY:APA91bGFerYPN56D0NJRXKUK1eOgij3Yb_N0XuBgs4efT2b4U9Qdq2hqbpHloHIjMNhZxhaWaMv8k9n-kAGff5TndZnkk1jj3PYGLbmt6jsuWJoXbM8VFIGRj-EcmnJCQfQpriSrMsTN" + } + ) + + @POST("fcm/send") + Call sendNotification(@Body Sender body); +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/ChatsFragment.java b/app/src/main/java/com/saharsh/chatapp/Fragments/ChatsFragment.java new file mode 100644 index 0000000..f7ece28 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/ChatsFragment.java @@ -0,0 +1,157 @@ +package com.saharsh.chatapp.Fragments; + +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v7.widget.DividerItemDecoration; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.google.firebase.iid.FirebaseInstanceId; +import com.saharsh.chatapp.Adapter.OnItemClick; +import com.saharsh.chatapp.Adapter.UserAdapter; +import com.saharsh.chatapp.MainActivity; +import com.saharsh.chatapp.Model.Chatlist; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.Notifications.Token; +import com.saharsh.chatapp.R; + +import java.util.ArrayList; +import java.util.List; + + +public class ChatsFragment extends Fragment { + + private RecyclerView recyclerView; + + Typeface MR, MRR; + private UserAdapter userAdapter; + private List mUsers; + FrameLayout frameLayout; + TextView es_descp, es_title; + + FirebaseUser fuser; + DatabaseReference reference; + + private List usersList; + static OnItemClick onItemClick; + + + public static ChatsFragment newInstance(OnItemClick click) { + + onItemClick = click; + Bundle args = new Bundle(); + + ChatsFragment fragment = new ChatsFragment(); + fragment.setArguments(args); + return fragment; + } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_chats, container, false); + + MRR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriad.ttf"); + + recyclerView = view.findViewById(R.id.recycler_view); + frameLayout = view.findViewById(R.id.es_layout); + es_descp = view.findViewById(R.id.es_descp); + es_title = view.findViewById(R.id.es_title); + + es_descp.setTypeface(MR); + es_title.setTypeface(MRR); + + + + + recyclerView.setHasFixedSize(true); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL); + recyclerView.addItemDecoration(dividerItemDecoration); + + + fuser = FirebaseAuth.getInstance().getCurrentUser(); + + usersList = new ArrayList<>(); + + reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser.getUid()); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + usersList.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chatlist chatlist = snapshot.getValue(Chatlist.class); + usersList.add(chatlist); + } + if(usersList.size()==0){ + frameLayout.setVisibility(View.VISIBLE); + } + else{ + frameLayout.setVisibility(View.GONE); + } + + chatList(); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + updateToken(FirebaseInstanceId.getInstance().getToken()); + + + return view; + } + + private void updateToken(String token){ + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens"); + Token token1 = new Token(token); + reference.child(fuser.getUid()).setValue(token1); + } + + private void chatList() { + mUsers = new ArrayList<>(); + reference = FirebaseDatabase.getInstance().getReference("Users"); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + mUsers.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + User user = snapshot.getValue(User.class); + for (Chatlist chatlist : usersList){ + if (user!= null && user.getId()!=null && chatlist!=null && chatlist.getId()!= null && + user.getId().equals(chatlist.getId())){ + mUsers.add(user); + } + } + } + + + userAdapter = new UserAdapter(getContext(), onItemClick,mUsers, true); + recyclerView.setAdapter(userAdapter); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/ProfileFragment.java b/app/src/main/java/com/saharsh/chatapp/Fragments/ProfileFragment.java new file mode 100644 index 0000000..2744e2a --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/ProfileFragment.java @@ -0,0 +1,253 @@ +package com.saharsh.chatapp.Fragments; + +import android.app.ProgressDialog; +import android.content.ContentResolver; +import android.content.Intent; +import android.graphics.Typeface; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.MimeTypeMap; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.android.gms.tasks.Continuation; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import com.google.firebase.storage.StorageTask; +import com.google.firebase.storage.UploadTask; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.R; + +import java.util.HashMap; + +import de.hdodenhof.circleimageview.CircleImageView; + +import static android.app.Activity.RESULT_OK; + + +public class ProfileFragment extends Fragment { + + CircleImageView image_profile; + TextView profile_tv; + EditText username, bio_et; + ImageView edit_img; + Button save; + DatabaseReference reference; + FirebaseUser fuser; + Typeface MR,MRR; + + StorageReference storageReference; + private static final int IMAGE_REQUEST = 1; + private Uri imageUri; + private StorageTask uploadTask; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_profile, container, false); + MRR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriad.ttf"); + + + image_profile = view.findViewById(R.id.profile_image); + username = view.findViewById(R.id.username); + profile_tv = view.findViewById(R.id.profile_tv); + bio_et = view.findViewById(R.id.bio_et); + edit_img = view.findViewById(R.id.edit_image); + save = view.findViewById(R.id.save_btn); + + + username.setTypeface(MR); + profile_tv.setTypeface(MR); + bio_et.setTypeface(MRR); + save.setTypeface(MR); + + storageReference = FirebaseStorage.getInstance().getReference("uploads"); + + fuser = FirebaseAuth.getInstance().getCurrentUser(); + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + + edit_img.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + save.setVisibility(View.VISIBLE); + username.setEnabled(true); + bio_et.setEnabled(true); + username.setSelection(username.getText().length()); + } + }); + + save.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + username.setEnabled(false); + bio_et.setEnabled(false); + + + reference.child("bio").setValue(bio_et.getText().toString().trim()).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + // Toast.makeText(getContext(),"Profile Updated...", Toast.LENGTH_SHORT); + } + else{ + // Toast.makeText(getContext(),"Unable to Save...", Toast.LENGTH_SHORT); + + } + } + }); + + + + reference.child("username").setValue(username.getText().toString().trim()).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Toast.makeText(getContext(),"Profile Updated...", Toast.LENGTH_SHORT); + } + else{ + Toast.makeText(getContext(),"Unable to Save...", Toast.LENGTH_SHORT); + + } + } + }); + + save.setVisibility(View.GONE); + } + + }); + + + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if(isAdded()){ + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + bio_et.setText(user.getBio()); + if (user.getImageURL().equals("default")){ + image_profile.setImageResource(R.drawable.profile_img); + } else { + Glide.with(getContext()).load(user.getImageURL()).into(image_profile); + } + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + image_profile.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openImage(); + } + }); + + return view; + } + + private void openImage() { + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(intent, IMAGE_REQUEST); + } + + private String getFileExtension(Uri uri){ + ContentResolver contentResolver = getContext().getContentResolver(); + MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); + return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri)); + } + + private void uploadImage(){ + final ProgressDialog pd = new ProgressDialog(getContext()); + pd.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ic_picture)); + + pd.setMessage("Uploading..."); + pd.show(); + + if (imageUri != null){ + final StorageReference fileReference = storageReference.child(System.currentTimeMillis() + +"."+getFileExtension(imageUri)); + + uploadTask = fileReference.putFile(imageUri); + uploadTask.continueWithTask(new Continuation>() { + @Override + public Task then(@NonNull Task task) throws Exception { + if (!task.isSuccessful()){ + throw task.getException(); + } + + return fileReference.getDownloadUrl(); + } + }).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Uri downloadUri = task.getResult(); + String mUri = downloadUri.toString(); + + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + HashMap map = new HashMap<>(); + map.put("imageURL", ""+mUri); + reference.updateChildren(map); + + pd.dismiss(); + } else { + Toast.makeText(getContext(), "Failed!", Toast.LENGTH_SHORT).show(); + pd.dismiss(); + } + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + pd.dismiss(); + } + }); + } else { + Toast.makeText(getContext(), "No image selected", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == IMAGE_REQUEST && resultCode == RESULT_OK + && data != null && data.getData() != null){ + imageUri = data.getData(); + + if (uploadTask != null && uploadTask.isInProgress()){ + Toast.makeText(getContext(), "Upload in progress", Toast.LENGTH_SHORT).show(); + } else { + uploadImage(); + } + } + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/UsersFragment.java b/app/src/main/java/com/saharsh/chatapp/Fragments/UsersFragment.java new file mode 100644 index 0000000..6a5a8dd --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/UsersFragment.java @@ -0,0 +1,176 @@ +package com.saharsh.chatapp.Fragments; + +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v7.widget.DividerItemDecoration; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.Query; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Adapter.OnItemClick; +import com.saharsh.chatapp.Adapter.UserAdapter; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.R; + +import java.util.ArrayList; +import java.util.List; + + +public class UsersFragment extends Fragment { + + private RecyclerView recyclerView; + + Typeface MR, MRR; + FrameLayout frameLayout; + TextView es_descp, es_title; + + private UserAdapter userAdapter; + private List mUsers; + static OnItemClick onItemClick; + + EditText search_users; + + public static UsersFragment newInstance(OnItemClick click) { + onItemClick = click; + Bundle args = new Bundle(); + + UsersFragment fragment = new UsersFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.fragment_users, container, false); + + + MRR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriad.ttf"); + + recyclerView = view.findViewById(R.id.recycler_view); + frameLayout = view.findViewById(R.id.es_layout); + es_descp = view.findViewById(R.id.es_descp); + es_title = view.findViewById(R.id.es_title); + + es_descp.setTypeface(MR); + es_title.setTypeface(MRR); + + recyclerView.setHasFixedSize(true); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL); + recyclerView.addItemDecoration(dividerItemDecoration); + + mUsers = new ArrayList<>(); + + readUsers(); + + search_users = view.findViewById(R.id.search_users); + search_users.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + searchUsers(charSequence.toString().toLowerCase()); + } + + @Override + public void afterTextChanged(Editable editable) { + + } + }); + + return view; + } + + private void searchUsers(String s) { + + final FirebaseUser fuser = FirebaseAuth.getInstance().getCurrentUser(); + Query query = FirebaseDatabase.getInstance().getReference("Users").orderByChild("search") + .startAt(s) + .endAt(s+"\uf8ff"); + + query.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + mUsers.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + User user = snapshot.getValue(User.class); + + assert user != null; + assert fuser != null; + if (!user.getId().equals(fuser.getUid())){ + mUsers.add(user); + } + } + + userAdapter = new UserAdapter(getContext(),onItemClick, mUsers, false); + recyclerView.setAdapter(userAdapter); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + } + + private void readUsers() { + + final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users"); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if (search_users.getText().toString().equals("")) { + mUsers.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + User user = snapshot.getValue(User.class); + + if (user!= null && user.getId()!=null && firebaseUser!=null && !user.getId().equals(firebaseUser.getUid())) { + mUsers.add(user); + } + } + + if(mUsers.size()==0){ + frameLayout.setVisibility(View.VISIBLE); + } + else{ + frameLayout.setVisibility(View.GONE); + } + + userAdapter = new UserAdapter(getContext(), onItemClick,mUsers, false); + recyclerView.setAdapter(userAdapter); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/LoginActivity.java b/app/src/main/java/com/saharsh/chatapp/LoginActivity.java new file mode 100644 index 0000000..1ee89eb --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/LoginActivity.java @@ -0,0 +1,106 @@ +package com.saharsh.chatapp; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; + +public class LoginActivity extends AppCompatActivity { + + EditText email, password; + Button btn_login; + Typeface MR,MRR; + ProgressDialog dialog; + + FirebaseAuth auth; + TextView forgot_password, login_tv, msg_tv; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle("Login"); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + auth = FirebaseAuth.getInstance(); + + login_tv = findViewById(R.id.login_tv); + email = findViewById(R.id.email); + password = findViewById(R.id.password); + btn_login = findViewById(R.id.btn_login); + forgot_password = findViewById(R.id.forgot_password); + msg_tv = findViewById(R.id.msg_tv); + + msg_tv.setTypeface(MRR); + login_tv.setTypeface(MR); + email.setTypeface(MRR); + password.setTypeface(MRR); + btn_login.setTypeface(MRR); + forgot_password.setTypeface(MRR); + + forgot_password.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(LoginActivity.this, ResetPasswordActivity.class)); + } + }); + + btn_login.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String txt_email = email.getText().toString(); + String txt_password = password.getText().toString(); + + Utils.hideKeyboard(LoginActivity.this); + + if (TextUtils.isEmpty(txt_email) || TextUtils.isEmpty(txt_password)){ + Toast.makeText(LoginActivity.this, "All fields are required", Toast.LENGTH_SHORT).show(); + } else { + + dialog = Utils.showLoader(LoginActivity.this); + auth.signInWithEmailAndPassword(txt_email, txt_password) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Intent intent = new Intent(LoginActivity.this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + if(dialog!=null){ + dialog.dismiss(); + } + startActivity(intent); + finish(); + } else { + if(dialog!=null){ + dialog.dismiss(); + } + Toast.makeText(LoginActivity.this, "Authentication failed!", Toast.LENGTH_SHORT).show(); + + } + } + }); + } + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/MainActivity.java b/app/src/main/java/com/saharsh/chatapp/MainActivity.java new file mode 100644 index 0000000..6e06679 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/MainActivity.java @@ -0,0 +1,251 @@ +package com.saharsh.chatapp; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Adapter.OnItemClick; +import com.saharsh.chatapp.Fragments.ChatsFragment; +import com.saharsh.chatapp.Fragments.ProfileFragment; +import com.saharsh.chatapp.Fragments.UsersFragment; +import com.saharsh.chatapp.Model.Chat; +import com.saharsh.chatapp.Model.User; + +import java.util.ArrayList; +import java.util.HashMap; + +import de.hdodenhof.circleimageview.CircleImageView; + +public class MainActivity extends AppCompatActivity implements OnItemClick { + + boolean doubleBackToExitPressedOnce = false; + CircleImageView profile_image; + TextView username; + ProgressDialog dialog; + Typeface MR,MRR; + + FirebaseUser firebaseUser; + DatabaseReference reference; + OnItemClick onItemClick; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + this.onItemClick = this; + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle(""); + + profile_image = findViewById(R.id.profile_image); + final TabLayout tabLayout = findViewById(R.id.tab_layout); + final ViewPager viewPager = findViewById(R.id.view_pager); + + profile_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + TabLayout.Tab tab = tabLayout.getTabAt(2); + tab.select(); + + } + }); + username = findViewById(R.id.username); + username.setTypeface(MR); + + firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser.getUid()); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + if (user.getImageURL().equals("default")){ + profile_image.setImageResource(R.drawable.profile_img); + } else { + //change this + Glide.with(getApplicationContext()).load(user.getImageURL()).into(profile_image); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + + reference = FirebaseDatabase.getInstance().getReference("Chats"); + dialog = Utils.showLoader(MainActivity.this); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); + int unread = 0; + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (chat.getReceiver().equals(firebaseUser.getUid()) && !chat.isIsseen()){ + unread++; + } + } + + if (unread == 0){ + viewPagerAdapter.addFragment(ChatsFragment.newInstance(onItemClick), "Chats"); + } else { + viewPagerAdapter.addFragment(ChatsFragment.newInstance(onItemClick), "("+unread+") Chats"); + } + + viewPagerAdapter.addFragment(UsersFragment.newInstance(onItemClick), "Users"); + viewPagerAdapter.addFragment(new ProfileFragment(), "Profile"); + + viewPager.setAdapter(viewPagerAdapter); + + tabLayout.setupWithViewPager(viewPager); + if(dialog!=null){ + dialog.dismiss(); + } + + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()){ + + case R.id.logout: + FirebaseAuth.getInstance().signOut(); + // change this code beacuse your app will crash + startActivity(new Intent(MainActivity.this, StartActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); + return true; + } + + return false; + } + + @Override + public void onItemCLick(String uid, View view) { + + ViewProfileActivity viewProfileActivity = + ViewProfileActivity.newInstance(uid,this); + viewProfileActivity.show(getSupportFragmentManager(), + "view_profile"); + + } + + class ViewPagerAdapter extends FragmentPagerAdapter { + + private ArrayList fragments; + private ArrayList titles; + + ViewPagerAdapter(FragmentManager fm){ + super(fm); + this.fragments = new ArrayList<>(); + this.titles = new ArrayList<>(); + } + + @Override + public Fragment getItem(int position) { + return fragments.get(position); + } + + @Override + public int getCount() { + return fragments.size(); + } + + public void addFragment(Fragment fragment, String title){ + fragments.add(fragment); + titles.add(title); + } + + // Ctrl + O + + @Nullable + @Override + public CharSequence getPageTitle(int position) { + return titles.get(position); + } + } + + private void status(String status){ + reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser.getUid()); + + HashMap hashMap = new HashMap<>(); + hashMap.put("status", status); + + reference.updateChildren(hashMap); + } + + @Override + protected void onResume() { + super.onResume(); + status("online"); + } + + @Override + protected void onPause() { + super.onPause(); + status("offline"); + } + + @Override + public void onBackPressed() { + if (doubleBackToExitPressedOnce) { + super.onBackPressed(); + return; + } + + this.doubleBackToExitPressedOnce = true; + Toast.makeText(this, "Please click Back again to exit", Toast.LENGTH_SHORT).show(); + + new Handler().postDelayed(new Runnable() { + + @Override + public void run() { + doubleBackToExitPressedOnce=false; + } + }, 2000); } +} diff --git a/app/src/main/java/com/saharsh/chatapp/MessageActivity.java b/app/src/main/java/com/saharsh/chatapp/MessageActivity.java new file mode 100644 index 0000000..9118575 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/MessageActivity.java @@ -0,0 +1,332 @@ +package com.saharsh.chatapp; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.Query; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Adapter.MessageAdapter; +import com.saharsh.chatapp.Fragments.APIService; +import com.saharsh.chatapp.Model.Chat; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.Notifications.Client; +import com.saharsh.chatapp.Notifications.Data; +import com.saharsh.chatapp.Notifications.MyResponse; +import com.saharsh.chatapp.Notifications.Token; +import com.saharsh.chatapp.Notifications.Sender; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import de.hdodenhof.circleimageview.CircleImageView; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class MessageActivity extends AppCompatActivity { + + CircleImageView profile_image; + TextView username; + + Typeface MR, MRR; + + FirebaseUser fuser; + DatabaseReference reference; + + ImageButton btn_send; + EditText text_send; + + MessageAdapter messageAdapter; + List mchat; + + RecyclerView recyclerView; + + Intent intent; + + ValueEventListener seenListener; + + String userid; + + APIService apiService; + + boolean notify = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_message); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle(""); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + // and this + startActivity(new Intent(MessageActivity.this, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); + } + }); + + apiService = Client.getClient("https://fcm.googleapis.com/").create(APIService.class); + + recyclerView = findViewById(R.id.recycler_view); + recyclerView.setHasFixedSize(true); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext()); + linearLayoutManager.setStackFromEnd(true); + recyclerView.setLayoutManager(linearLayoutManager); + + profile_image = findViewById(R.id.profile_image); + username = findViewById(R.id.username); + btn_send = findViewById(R.id.btn_send); + text_send = findViewById(R.id.text_send); + + username.setTypeface(MR); + text_send.setTypeface(MRR); + + + intent = getIntent(); + userid = intent.getStringExtra("userid"); + fuser = FirebaseAuth.getInstance().getCurrentUser(); + + btn_send.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + notify = true; + String msg = text_send.getText().toString(); + String time = String.valueOf(System.currentTimeMillis()); + if (!msg.equals("")){ + sendMessage(fuser.getUid(), userid, msg, time); + } else { + Toast.makeText(MessageActivity.this, "You can't send empty message", Toast.LENGTH_SHORT).show(); + } + text_send.setText(""); + } + }); + + + reference = FirebaseDatabase.getInstance().getReference("Users").child(userid); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + if (user.getImageURL().equals("default")){ + profile_image.setImageResource(R.drawable.profile_img); + } else { + //and this + Glide.with(getApplicationContext()).load(user.getImageURL()).into(profile_image); + } + + readMesagges(fuser.getUid(), userid, user.getImageURL()); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + seenMessage(userid); + } + + private void seenMessage(final String userid){ + reference = FirebaseDatabase.getInstance().getReference("Chats"); + seenListener = reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (chat.getReceiver().equals(fuser.getUid()) && chat.getSender().equals(userid)){ + HashMap hashMap = new HashMap<>(); + hashMap.put("isseen", true); + snapshot.getRef().updateChildren(hashMap); + } + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void sendMessage(String sender, final String receiver, String message, String time){ + + DatabaseReference reference = FirebaseDatabase.getInstance().getReference(); + + HashMap hashMap = new HashMap<>(); + hashMap.put("sender", sender); + hashMap.put("receiver", receiver); + hashMap.put("message", message); + hashMap.put("isseen", false); + hashMap.put("time", time); + + reference.child("Chats").push().setValue(hashMap); + + + // add user to chat fragment + final DatabaseReference chatRef = FirebaseDatabase.getInstance().getReference("Chatlist") + .child(fuser.getUid()) + .child(userid); + + chatRef.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if (!dataSnapshot.exists()){ + chatRef.child("id").setValue(userid); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + final DatabaseReference chatRefReceiver = FirebaseDatabase.getInstance().getReference("Chatlist") + .child(userid) + .child(fuser.getUid()); + chatRefReceiver.child("id").setValue(fuser.getUid()); + + final String msg = message; + + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + if (notify) { + sendNotifiaction(receiver, user.getUsername(), msg); + } + notify = false; + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void sendNotifiaction(String receiver, final String username, final String message){ + DatabaseReference tokens = FirebaseDatabase.getInstance().getReference("Tokens"); + Query query = tokens.orderByKey().equalTo(receiver); + query.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Token token = snapshot.getValue(Token.class); + Data data = new Data(fuser.getUid(), R.drawable.profile_img, username+": "+message, "New Message", + userid); + + Sender sender = new Sender(data, token.getToken()); + + apiService.sendNotification(sender) + .enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.code() == 200){ + if (response.body().success != 1){ + //Toast.makeText(MessageActivity.this, "Failed!", Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + + } + }); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void readMesagges(final String myid, final String userid, final String imageurl){ + mchat = new ArrayList<>(); + + reference = FirebaseDatabase.getInstance().getReference("Chats"); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + mchat.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (chat.getReceiver().equals(myid) && chat.getSender().equals(userid) || + chat.getReceiver().equals(userid) && chat.getSender().equals(myid)){ + mchat.add(chat); + } + + messageAdapter = new MessageAdapter(MessageActivity.this, mchat, imageurl); + recyclerView.setAdapter(messageAdapter); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void currentUser(String userid){ + SharedPreferences.Editor editor = getSharedPreferences("PREFS", MODE_PRIVATE).edit(); + editor.putString("currentuser", userid); + editor.apply(); + } + + private void status(String status){ + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + + HashMap hashMap = new HashMap<>(); + hashMap.put("status", status); + + reference.updateChildren(hashMap); + } + + @Override + protected void onResume() { + super.onResume(); + status("online"); + currentUser(userid); + } + + @Override + protected void onPause() { + super.onPause(); + reference.removeEventListener(seenListener); + status("offline"); + currentUser("none"); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Model/Chat.java b/app/src/main/java/com/saharsh/chatapp/Model/Chat.java new file mode 100644 index 0000000..c73b9e5 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Model/Chat.java @@ -0,0 +1,61 @@ +package com.saharsh.chatapp.Model; + +public class Chat { + + private String sender; + private String receiver; + private String message; + private boolean isseen; + private String time; + + public Chat(String sender, String receiver, String message, boolean isseen, String time) { + this.sender = sender; + this.receiver = receiver; + this.message = message; + this.isseen = isseen; + this.time = time; + } + + public Chat() { + } + + public String getSender() { + return sender; + } + + public void setSender(String sender) { + this.sender = sender; + } + + public String getReceiver() { + return receiver; + } + + public void setReceiver(String receiver) { + this.receiver = receiver; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isIsseen() { + return isseen; + } + + public void setIsseen(boolean isseen) { + this.isseen = isseen; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Model/Chatlist.java b/app/src/main/java/com/saharsh/chatapp/Model/Chatlist.java new file mode 100644 index 0000000..9ae68c2 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Model/Chatlist.java @@ -0,0 +1,20 @@ +package com.saharsh.chatapp.Model; + +public class Chatlist { + public String id; + + public Chatlist(String id) { + this.id = id; + } + + public Chatlist() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Model/User.java b/app/src/main/java/com/saharsh/chatapp/Model/User.java new file mode 100644 index 0000000..de70900 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Model/User.java @@ -0,0 +1,73 @@ +package com.saharsh.chatapp.Model; + +public class User { + + private String id; + private String username; + private String imageURL; + private String status; + private String search; + private String bio; + + + public User(String id, String username, String imageURL, String status, String search, String bio) { + this.id = id; + this.username = username; + this.imageURL = imageURL; + this.status = status; + this.search = search; + this.bio = bio; + } + + public User() { + + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getImageURL() { + return imageURL; + } + + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getSearch() { + return search; + } + + public void setSearch(String search) { + this.search = search; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Client.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Client.java new file mode 100644 index 0000000..245f5ae --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Client.java @@ -0,0 +1,19 @@ +package com.saharsh.chatapp.Notifications; + +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class Client { + + private static Retrofit retrofit = null; + + public static Retrofit getClient(String url){ + if (retrofit == null){ + retrofit = new Retrofit.Builder() + .baseUrl(url) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + } + return retrofit; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Data.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Data.java new file mode 100644 index 0000000..c0e479f --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Data.java @@ -0,0 +1,60 @@ +package com.saharsh.chatapp.Notifications; + +public class Data { + private String user; + private int icon; + private String body; + private String title; + private String sented; + + public Data(String user, int icon, String body, String title, String sented) { + this.user = user; + this.icon = icon; + this.body = body; + this.title = title; + this.sented = sented; + } + + public Data() { + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public int getIcon() { + return icon; + } + + public void setIcon(int icon) { + this.icon = icon; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSented() { + return sented; + } + + public void setSented(String sented) { + this.sented = sented; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseIdService.java b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseIdService.java new file mode 100644 index 0000000..6228d46 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseIdService.java @@ -0,0 +1,30 @@ +package com.saharsh.chatapp.Notifications; + +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.iid.FirebaseInstanceId; +import com.google.firebase.iid.FirebaseInstanceIdService; + +public class MyFirebaseIdService extends FirebaseInstanceIdService { + + @Override + public void onTokenRefresh() { + super.onTokenRefresh(); + FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + String refreshToken = FirebaseInstanceId.getInstance().getToken(); + if (firebaseUser != null){ + updateToken(refreshToken); + } + } + + private void updateToken(String refreshToken) { + FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens"); + Token token = new Token(refreshToken); + reference.child(firebaseUser.getUid()).setValue(token); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseMessaging.java b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseMessaging.java new file mode 100644 index 0000000..6e8b78d --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseMessaging.java @@ -0,0 +1,108 @@ +package com.saharsh.chatapp.Notifications; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; +import com.saharsh.chatapp.MessageActivity; + +public class MyFirebaseMessaging extends FirebaseMessagingService { + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + super.onMessageReceived(remoteMessage); + + String sented = remoteMessage.getData().get("sented"); + String user = remoteMessage.getData().get("user"); + + SharedPreferences preferences = getSharedPreferences("PREFS", MODE_PRIVATE); + String currentUser = preferences.getString("currentuser", "none"); + + FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + if (firebaseUser != null && sented.equals(firebaseUser.getUid())){ + if (!currentUser.equals(user)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + sendOreoNotification(remoteMessage); + } else { + sendNotification(remoteMessage); + } + } + } + } + + private void sendOreoNotification(RemoteMessage remoteMessage){ + String user = remoteMessage.getData().get("user"); + String icon = remoteMessage.getData().get("icon"); + String title = remoteMessage.getData().get("title"); + String body = remoteMessage.getData().get("body"); + + RemoteMessage.Notification notification = remoteMessage.getNotification(); + int j = Integer.parseInt(user.replaceAll("[\\D]", "")); + Intent intent = new Intent(this, MessageActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("userid", user); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + PendingIntent pendingIntent = PendingIntent.getActivity(this, j, intent, PendingIntent.FLAG_ONE_SHOT); + Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + + com.saharsh.chatapp.Notifications.OreoNotification oreoNotification = new com.saharsh.chatapp.Notifications.OreoNotification(this); + Notification.Builder builder = oreoNotification.getOreoNotification(title, body, pendingIntent, + defaultSound, icon); + + int i = 0; + if (j > 0){ + i = j; + } + + oreoNotification.getManager().notify(i, builder.build()); + + } + + private void sendNotification(RemoteMessage remoteMessage) { + + String user = remoteMessage.getData().get("user"); + String icon = remoteMessage.getData().get("icon"); + String title = remoteMessage.getData().get("title"); + String body = remoteMessage.getData().get("body"); + + RemoteMessage.Notification notification = remoteMessage.getNotification(); + int j = Integer.parseInt(user.replaceAll("[\\D]", "")); + Intent intent = new Intent(this, MessageActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("userid", user); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + PendingIntent pendingIntent = PendingIntent.getActivity(this, j, intent, PendingIntent.FLAG_ONE_SHOT); + + Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + NotificationCompat.Builder builder = new NotificationCompat.Builder(this) + .setSmallIcon(Integer.parseInt(icon)) + .setContentTitle(title) + .setContentText(body) + .setAutoCancel(true) + .setSound(defaultSound) + .setContentIntent(pendingIntent); + NotificationManager noti = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + + int i = 0; + if (j > 0){ + i = j; + } + + noti.notify(i, builder.build()); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/MyResponse.java b/app/src/main/java/com/saharsh/chatapp/Notifications/MyResponse.java new file mode 100644 index 0000000..766dbe4 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/MyResponse.java @@ -0,0 +1,6 @@ +package com.saharsh.chatapp.Notifications; + +public class MyResponse { + + public int success; +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/OreoNotification.java b/app/src/main/java/com/saharsh/chatapp/Notifications/OreoNotification.java new file mode 100644 index 0000000..a802e66 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/OreoNotification.java @@ -0,0 +1,60 @@ +package com.saharsh.chatapp.Notifications; + +import android.annotation.TargetApi; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.ContextWrapper; +import android.net.Uri; +import android.os.Build; + +public class OreoNotification extends ContextWrapper { + + private static final String CHANNEL_ID = "com.koddev.chatapp"; + private static final String CHANNEL_NAME = "chatapp"; + + private NotificationManager notificationManager; + + public OreoNotification(Context base) { + super(base); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + createChannel(); + } + } + + @TargetApi(Build.VERSION_CODES.O) + private void createChannel() { + + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + CHANNEL_NAME, + NotificationManager.IMPORTANCE_DEFAULT); + channel.enableLights(false); + channel.enableVibration(true); + channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); + + getManager().createNotificationChannel(channel); + } + + public NotificationManager getManager(){ + if (notificationManager == null){ + notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + } + + return notificationManager; + } + + @TargetApi(Build.VERSION_CODES.O) + public Notification.Builder getOreoNotification(String title, String body, + PendingIntent pendingIntent, Uri soundUri, String icon){ + return new Notification.Builder(getApplicationContext(), CHANNEL_ID) + .setContentIntent(pendingIntent) + .setContentTitle(title) + .setContentText(body) + .setSmallIcon(Integer.parseInt(icon)) + .setSound(soundUri) + .setAutoCancel(true); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Sender.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Sender.java new file mode 100644 index 0000000..51b6bd4 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Sender.java @@ -0,0 +1,11 @@ +package com.saharsh.chatapp.Notifications; + +public class Sender { + public Data data; + public String to; + + public Sender(Data data, String to) { + this.data = data; + this.to = to; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Token.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Token.java new file mode 100644 index 0000000..3a09527 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Token.java @@ -0,0 +1,20 @@ +package com.saharsh.chatapp.Notifications; + +public class Token { + private String token; + + public Token(String token) { + this.token = token; + } + + public Token() { + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/RegisterActivity.java b/app/src/main/java/com/saharsh/chatapp/RegisterActivity.java new file mode 100644 index 0000000..f5dad86 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/RegisterActivity.java @@ -0,0 +1,131 @@ +package com.saharsh.chatapp; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +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.rengwuxian.materialedittext.MaterialEditText; + +import java.util.HashMap; + +public class RegisterActivity extends AppCompatActivity { + + EditText username, email, password; + TextView register_tv, msg_reg_tv; + Button btn_register; + Typeface MR, MRR; + FirebaseAuth auth; + DatabaseReference reference; + ProgressDialog dialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle("Register"); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + username = findViewById(R.id.username); + email = findViewById(R.id.email); + password = findViewById(R.id.password); + btn_register = findViewById(R.id.btn_register); + register_tv = findViewById(R.id.register_tv); + msg_reg_tv = findViewById(R.id.msg_reg_tv); + + msg_reg_tv.setTypeface(MRR); + username.setTypeface(MRR); + email.setTypeface(MRR); + password.setTypeface(MRR); + btn_register.setTypeface(MR); + register_tv.setTypeface(MR); + + auth = FirebaseAuth.getInstance(); + + btn_register.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String txt_username = username.getText().toString(); + String txt_email = email.getText().toString(); + String txt_password = password.getText().toString(); + Utils.hideKeyboard(RegisterActivity.this); + + if (TextUtils.isEmpty(txt_username) || TextUtils.isEmpty(txt_email) || TextUtils.isEmpty(txt_password)){ + Toast.makeText(RegisterActivity.this, "All fileds are required", Toast.LENGTH_SHORT).show(); + } else if (txt_password.length() < 6 ){ + Toast.makeText(RegisterActivity.this, "password must be at least 6 characters", Toast.LENGTH_SHORT).show(); + } else { + register(txt_username, txt_email, txt_password); + } + } + }); + } + + private void register(final String username, String email, String password){ + + dialog = Utils.showLoader(RegisterActivity.this); + + auth.createUserWithEmailAndPassword(email, password) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + FirebaseUser firebaseUser = auth.getCurrentUser(); + assert firebaseUser != null; + String userid = firebaseUser.getUid(); + + reference = FirebaseDatabase.getInstance().getReference("Users").child(userid); + + HashMap hashMap = new HashMap<>(); + hashMap.put("id", userid); + hashMap.put("username", username); + hashMap.put("imageURL", "default"); + hashMap.put("status", "offline"); + hashMap.put("bio", ""); + hashMap.put("search", username.toLowerCase()); + if(dialog!=null){ + dialog.dismiss(); + } + reference.setValue(hashMap).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Intent intent = new Intent(RegisterActivity.this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); + } + } + }); + } else { + Toast.makeText(RegisterActivity.this, "You can't register woth this email or password", Toast.LENGTH_SHORT).show(); + if(dialog!=null){ + dialog.dismiss(); + } + } + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/ResetPasswordActivity.java b/app/src/main/java/com/saharsh/chatapp/ResetPasswordActivity.java new file mode 100644 index 0000000..648df08 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/ResetPasswordActivity.java @@ -0,0 +1,76 @@ +package com.saharsh.chatapp; + +import android.content.Intent; +import android.graphics.Typeface; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.FirebaseAuth; + +public class ResetPasswordActivity extends AppCompatActivity { + + EditText send_email; + Button btn_reset; + Typeface MR, MRR; + TextView hint_tv; + FirebaseAuth firebaseAuth; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_reset_password); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle("Reset Password"); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + send_email = findViewById(R.id.send_email); + btn_reset = findViewById(R.id.btn_reset); + hint_tv = findViewById(R.id.hint_tv); + + send_email.setTypeface(MRR); + btn_reset.setTypeface(MR); + hint_tv.setTypeface(MR); + + firebaseAuth = FirebaseAuth.getInstance(); + + btn_reset.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String email = send_email.getText().toString(); + Utils.hideKeyboard(ResetPasswordActivity.this); + + if (email.equals("")){ + Toast.makeText(ResetPasswordActivity.this, "All fileds are required!", Toast.LENGTH_SHORT).show(); + } else { + firebaseAuth.sendPasswordResetEmail(email).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Toast.makeText(ResetPasswordActivity.this, "Please check you Email", Toast.LENGTH_SHORT).show(); + startActivity(new Intent(ResetPasswordActivity.this, LoginActivity.class)); + } else { + String error = task.getException().getMessage(); + Toast.makeText(ResetPasswordActivity.this, error, Toast.LENGTH_SHORT).show(); + } + } + }); + } + } + }); + + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/StartActivity.java b/app/src/main/java/com/saharsh/chatapp/StartActivity.java new file mode 100644 index 0000000..0d3752e --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/StartActivity.java @@ -0,0 +1,69 @@ +package com.saharsh.chatapp; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +public class StartActivity extends AppCompatActivity { + + Button login, register; + TextView chat_title_tv; + Typeface MR, MRR; + + FirebaseUser firebaseUser; + + @Override + protected void onStart() { + super.onStart(); + + + firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + //check if user is null + if (firebaseUser != null){ + Intent intent = new Intent(StartActivity.this, MainActivity.class); + startActivity(intent); + finish(); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_start); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + + + login = findViewById(R.id.login); + register = findViewById(R.id.register); + chat_title_tv = findViewById(R.id.chat_title_tv); + + login.setTypeface(MR); + register.setTypeface(MR); + chat_title_tv.setTypeface(MR); + + login.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(StartActivity.this, LoginActivity.class)); + } + }); + + register.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(StartActivity.this, RegisterActivity.class)); + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Utils.java b/app/src/main/java/com/saharsh/chatapp/Utils.java new file mode 100644 index 0000000..d06dd49 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Utils.java @@ -0,0 +1,46 @@ +package com.saharsh.chatapp; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.ProgressBar; + +public class Utils { + + public static ProgressDialog showLoader(Context context){ + ProgressDialog dialog = new ProgressDialog(context); + try { + dialog.show(); + } catch (WindowManager.BadTokenException e) { + + } + dialog.setCancelable(false); + dialog.getWindow() + .setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); + dialog.setContentView(R.layout.progressdialog); + return dialog; + // dialog.setMessage(Message); + } + + public static void hideKeyboard(Activity activity) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); + //Find the currently focused view, so we can grab the correct window token from it. + View view = activity.getCurrentFocus(); + //If no view currently has focus, create a new one, just so we can grab a window token from it + if (view == null) { + view = new View(activity); + } + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + + public static void hideLoader(ProgressDialog dialog){ + // To dismiss the dialog + if(dialog!=null){ + dialog.dismiss(); + } + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/ViewProfileActivity.java b/app/src/main/java/com/saharsh/chatapp/ViewProfileActivity.java new file mode 100644 index 0000000..b91546d --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/ViewProfileActivity.java @@ -0,0 +1,87 @@ +package com.saharsh.chatapp; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.BottomSheetDialogFragment; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Model.User; + +public class ViewProfileActivity extends BottomSheetDialogFragment { + + String uid; + DatabaseReference reference; + TextView username, bio_et; + ImageView profile_img; + static Context mContext; + + + public ViewProfileActivity() { + + } + + public static ViewProfileActivity newInstance(String uid, Context context) { + + Bundle args = new Bundle(); + args.putString("uid",uid); + mContext = context; + ViewProfileActivity fragment = new ViewProfileActivity(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.activity_view_profile,container,false); + if(getArguments()!=null){ + uid = getArguments().getString("uid"); + profile_img = view.findViewById(R.id.view_profile_image); + username = view.findViewById(R.id.view_username); + bio_et = view.findViewById(R.id.view_bio_et); + + reference = FirebaseDatabase.getInstance().getReference("Users").child(uid); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + bio_et.setText(user.getBio()); + if (user.getImageURL().equals("default")){ + profile_img.setImageResource(R.drawable.profile_img); + } else { + //change this + Glide.with(mContext.getApplicationContext()).load(user.getImageURL()).into(profile_img); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + return view; + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_action_name.png b/app/src/main/res/drawable-hdpi/ic_action_name.png new file mode 100644 index 0000000000000000000000000000000000000000..36190ecc131ce8b3db2f16e6adcd35746eb1131f GIT binary patch literal 651 zcmV;60(AX}P)Vv)@rNhW;Yd7^r9E9JycMk7jqQElr&~{W=Fkv5w?eV@T!6l6xxD^ z96Yp&1*K4bv{d|~`kf`4tWZtj>}GagA3Op%?7Z*yeP-ru($o}39C5@Enb79u9_f^B zX_hrHlujp96>x^U)-CHOMd|x4LORqGP{~W3kdG-s22~YMPL0w%2zeV>ys8N(X9=%Y z%gfKz6yT+8UqlM8x&_=!`FIHmsNiK;87X-6EH1XWScnLaiPva0`#4F+??43n4==|_ zs4Ac_c!e&&j~AuRYsLoD6cE~fnatCaX%2B$bjIcl zN>}mlZ7lK~d8I5~ZifnmRxHrl$JjVfo53;3lD55$@Ak3iPvqZ#1?@KMa!ePCExi4= zbnlxGnmD~+*1RZQ_YcQ;;O;Mf_b9b}-TPI~D=5a43M*i;~xH0qVIWW-wFn1uaO z?_q+%JC*uX!o#GlOGmZ3+R=Ua4QuRsVV2=I1w9q zRLwmK2?-oPUnzs?5v81*C}7BxDist=09v#fh>zk3ja|T^K3%G~ScDim7?n#(#1sk& z41m7#0lGd7=+h>kA@hKECs6D(2?=u%koMAUXkf$co2)De5`00drN@D|1!%4=U9%yn z!Avy=5DaD-Ip74)x2?d0s7Kez2o}r|xw)crt&S-QW(piYonR)z0lR=jXa?1SndnAo tLBS$mS>R3eU?$isr*$xof>D44003N8KZnUVAj1Fv002ovPDHLkV1i%fw!{Dc literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/rounded_dialog.xml b/app/src/main/res/drawable-mdpi/rounded_dialog.xml new file mode 100644 index 0000000..e095b8a --- /dev/null +++ b/app/src/main/res/drawable-mdpi/rounded_dialog.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/ic_action_name.png b/app/src/main/res/drawable-xhdpi/ic_action_name.png new file mode 100644 index 0000000000000000000000000000000000000000..a92e695fa8aa33ad8f074ac0b34d96fe858dfbd8 GIT binary patch literal 641 zcmV-{0)G98P)P{}nqE;)Cy@64W$PGTueA_|=bg`+v0f}l}} zuRqE=hd37z&dtuu&OFJRT(-E~{mt{t%)4V*Mn*p z5Y#zqYi->Cqj<9!htj1uA=|9`!@9<6&)UVKTphVwBhJ(g+HpMLdGq)n>o_9&g5AS6 z9?G~!#OfiVdxXV9Qujy_kKc5p>2wqO-pF=?_}~k;G;iRGAK>o`tfy)KIKF>^E}I?< zf|&3ZWF4ThveIb-jNyyT*_0C2h1!Ii;e+1Qa6Wio?LGeYP$Wk250l^x!pyV-v_@eR z#o1iwD2lQMx|A+EnM|7%RecKp;M4_}9ZV);R@7Anpk#B~_eU(9#11JUZ*wCfBO@at bBklDHD_v!18XqL+p~<+Io;}=q#g_&SR7OM()l(Binh;cm zm1L2j4@u@9)mrCnPF|IW$g_vDJ~*60!E^U-?{DpIoqa1RNF)-8L?V$$Boc{4B9TZW zP=>M9Y0mG!eSd3j?@Ahxh?S6XZHn_TxTaH#4QDvNm=t0Y{HT&fCt3hAv#xP~aSc|* zb{Zi)0KyCG>2bpI4v;-*0-&zxB}&IVvL_7yW`hXq ziNc*80Q16Kla$+N)b#-P9qt%=guN%SCrtoCdtz)DiuTz=cXv%}?MWkmdG?el6tb}c zVF-XQQ(*5Yu&20$I|bmg5dh}yo;W}6ygk+R^sH0;of$(fx5FI*NHX@#U;u81JBt9g z8SX3u;8wV^9Dx1d&J_S<;ZBG%*4UF{0KzLF#MdC)ao%J!2v-4=g*#_36u@m)RBUsE}g?xA3o>cD%$HEwUYWMx6HH>Y*HgVeX_Q3Y;R7%Q1lJmO&=oLKh zq>H;JDB4$yu&2LJC0f|L)dRZ@xW5i+OX=8(l`xW?_b})^S=Sl|Tf>LO0-w$2Q{n32 zJX}2h=@a~aLM?v^cTuk#JnRdrV@o4ry8zIkvf3lWsEJ^#33vZP5S*4Jq)g1MJ@DZN z5DPp23X$ zyhuB2A%n?9FXSbVBN-vO z(}h98mi^SoGy zd+^{x>crg-Yu_`Y&A`OLq8_&$g;tw^&vp|NdSt~;osQGHqtIN`8DRqrK!FJy4w85@NA5p6aT(^rz_gr?X4Ff}yA0f5n=$zcF?geIo|m>!xO2QZ*J zG{q4B=97MGby(YUv#c7ATLYjp@Ix@@N3FA&KPKVQ(Zq4%ZKl+l zaqmr&kzZ4t)tkYiD{j4MS{T5XF@w+8AZ#O#J7qH#0GP~hehX^R4yR|kQ2G#IsmSPCTjq=8k#Hs;C5&-5`eOqScE3i06<`R*~s}xvYBWB zpv~M4Y=&lgL;y-QGn(YQhioQd0BAGtJ159yq6HB2X7D&7jZjnoRBtBD71_mpY z%dLSye-L~L0{%@SLL!k!Boc{4B9TZW5{X12{kwhv)a=O-w(A2^00000NkvXXu0mjf D8%;m$ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/background_left.xml b/app/src/main/res/drawable/background_left.xml new file mode 100644 index 0000000..ddd6486 --- /dev/null +++ b/app/src/main/res/drawable/background_left.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_right.xml b/app/src/main/res/drawable/background_right.xml new file mode 100644 index 0000000..5e80d63 --- /dev/null +++ b/app/src/main/res/drawable/background_right.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/button_bg.xml b/app/src/main/res/drawable/button_bg.xml new file mode 100644 index 0000000..540bc76 --- /dev/null +++ b/app/src/main/res/drawable/button_bg.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/edittext_bg.xml b/app/src/main/res/drawable/edittext_bg.xml new file mode 100644 index 0000000..f0b9c02 --- /dev/null +++ b/app/src/main/res/drawable/edittext_bg.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/es_image.xml b/app/src/main/res/drawable/es_image.xml new file mode 100644 index 0000000..93983c0 --- /dev/null +++ b/app/src/main/res/drawable/es_image.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_arrow_img.xml b/app/src/main/res/drawable/ic_arrow_img.xml new file mode 100644 index 0000000..744ffcf --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_img.xml @@ -0,0 +1,21 @@ + + + + diff --git a/app/src/main/res/drawable/ic_chevron_right.xml b/app/src/main/res/drawable/ic_chevron_right.xml new file mode 100644 index 0000000..1ba00ab --- /dev/null +++ b/app/src/main/res/drawable/ic_chevron_right.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/ic_cool_background.xml b/app/src/main/res/drawable/ic_cool_background.xml new file mode 100644 index 0000000..d64b13e --- /dev/null +++ b/app/src/main/res/drawable/ic_cool_background.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml new file mode 100644 index 0000000..46462b5 --- /dev/null +++ b/app/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_forgot_password.xml b/app/src/main/res/drawable/ic_forgot_password.xml new file mode 100644 index 0000000..fbe20f3 --- /dev/null +++ b/app/src/main/res/drawable/ic_forgot_password.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..ecfe93a --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_login.xml b/app/src/main/res/drawable/ic_login.xml new file mode 100644 index 0000000..dae0d44 --- /dev/null +++ b/app/src/main/res/drawable/ic_login.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_login_vector.xml b/app/src/main/res/drawable/ic_login_vector.xml new file mode 100644 index 0000000..69d0a85 --- /dev/null +++ b/app/src/main/res/drawable/ic_login_vector.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_next.xml b/app/src/main/res/drawable/ic_next.xml new file mode 100644 index 0000000..042c734 --- /dev/null +++ b/app/src/main/res/drawable/ic_next.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_picture.xml b/app/src/main/res/drawable/ic_picture.xml new file mode 100644 index 0000000..126a16b --- /dev/null +++ b/app/src/main/res/drawable/ic_picture.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_plus.xml b/app/src/main/res/drawable/ic_plus.xml new file mode 100644 index 0000000..d057a1f --- /dev/null +++ b/app/src/main/res/drawable/ic_plus.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/ic_send.xml b/app/src/main/res/drawable/ic_send.xml new file mode 100644 index 0000000..9951f35 --- /dev/null +++ b/app/src/main/res/drawable/ic_send.xml @@ -0,0 +1,21 @@ + + + + diff --git a/app/src/main/res/drawable/ic_signup_vector.xml b/app/src/main/res/drawable/ic_signup_vector.xml new file mode 100644 index 0000000..e84c9f0 --- /dev/null +++ b/app/src/main/res/drawable/ic_signup_vector.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_vector_chatapp.xml b/app/src/main/res/drawable/ic_vector_chatapp.xml new file mode 100644 index 0000000..0932ca3 --- /dev/null +++ b/app/src/main/res/drawable/ic_vector_chatapp.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/profile_img.xml b/app/src/main/res/drawable/profile_img.xml new file mode 100644 index 0000000..d87a573 --- /dev/null +++ b/app/src/main/res/drawable/profile_img.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rounded_edittext.xml b/app/src/main/res/drawable/rounded_edittext.xml new file mode 100644 index 0000000..06577cc --- /dev/null +++ b/app/src/main/res/drawable/rounded_edittext.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/search_bg.xml b/app/src/main/res/drawable/search_bg.xml new file mode 100644 index 0000000..0947372 --- /dev/null +++ b/app/src/main/res/drawable/search_bg.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..bb2a029 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + +