Feature/chat support feature (#1000)
* freshchat basic setups, sdk intergration, setting keys, initialization, show and send message * sdk integration, basic integration * "Chat UI fixes" Co-authored-by: Satish Prasad <satish.prasad@navi.com>
This commit is contained in:
committed by
Satish Prasad
parent
aea65cc2c3
commit
c177062a8d
@@ -88,6 +88,8 @@ android {
|
||||
buildConfigField 'String', 'HYPERVERGE_APP_ID', formatString('2c007b')
|
||||
buildConfigField 'String', 'SINGULAR_APP_KEY', formatString('navi_dev_edeadc40')
|
||||
buildConfigField 'String', 'SINGULAR_SECRET', formatString('6e5d72b8b2ac8e2f53ebc692ab1d3e65')
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_ID', formatString('85d4d958-e04b-447c-896c-9c7ff02d8a1a')
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_KEY', formatString('f829aae8-5aa7-4d40-8355-180c6459472a')
|
||||
}
|
||||
dev {
|
||||
applicationId "com.naviapp.dev"
|
||||
@@ -101,10 +103,12 @@ android {
|
||||
buildConfigField 'String', 'HYPERVERGE_APP_ID', formatString('2c007b')
|
||||
buildConfigField 'String', 'SINGULAR_APP_KEY', formatString('navi_dev_edeadc40')
|
||||
buildConfigField 'String', 'SINGULAR_SECRET', formatString('6e5d72b8b2ac8e2f53ebc692ab1d3e65')
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_ID', formatString('85d4d958-e04b-447c-896c-9c7ff02d8a1a')
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_KEY', formatString('f829aae8-5aa7-4d40-8355-180c6459472a')
|
||||
}
|
||||
prod {
|
||||
dimension "app"
|
||||
if (project.hasProperty('BASE_URL') && project.hasProperty('RAZORPAY_KEY') && project.hasProperty('MOENGAGE_KEY') && project.hasProperty('APPSFLYER_KEY') && project.hasProperty('UXCAM_KEY') && project.hasProperty('HYPERVERGE_APP_KEY') && project.hasProperty('HYPERVERGE_APP_ID') && project.hasProperty('SINGULAR_APP_KEY') && project.hasProperty('SINGULAR_SECRET')) {
|
||||
if (project.hasProperty('BASE_URL') && project.hasProperty('RAZORPAY_KEY') && project.hasProperty('MOENGAGE_KEY') && project.hasProperty('APPSFLYER_KEY') && project.hasProperty('UXCAM_KEY') && project.hasProperty('HYPERVERGE_APP_KEY') && project.hasProperty('HYPERVERGE_APP_ID') && project.hasProperty('SINGULAR_APP_KEY') && project.hasProperty('SINGULAR_SECRET') && project.hasProperty('FRESHCHAT_APP_ID') && project.hasProperty('FRESHCHAT_APP_KEY')) {
|
||||
buildConfigField 'String', 'BASE_URL', formatString("$BASE_URL")
|
||||
buildConfigField 'String', 'RAZORPAY_KEY', formatString("$RAZORPAY_KEY")
|
||||
buildConfigField 'String', 'MOENGAGE_KEY', formatString("$MOENGAGE_KEY")
|
||||
@@ -114,6 +118,9 @@ android {
|
||||
buildConfigField 'String', 'HYPERVERGE_APP_ID', formatString("$HYPERVERGE_APP_ID")
|
||||
buildConfigField 'String', 'SINGULAR_APP_KEY', formatString("$SINGULAR_APP_KEY")
|
||||
buildConfigField 'String', 'SINGULAR_SECRET', formatString("$SINGULAR_SECRET")
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_ID', formatString("$FRESHCHAT_APP_ID")
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_KEY', formatString("$FRESHCHAT_APP_KEY")
|
||||
|
||||
}
|
||||
}
|
||||
mockServer {
|
||||
@@ -128,6 +135,8 @@ android {
|
||||
buildConfigField 'String', 'HYPERVERGE_APP_ID', formatString('2c007b')
|
||||
buildConfigField 'String', 'SINGULAR_APP_KEY', formatString('navi_dev_edeadc40')
|
||||
buildConfigField 'String', 'SINGULAR_SECRET', formatString('6e5d72b8b2ac8e2f53ebc692ab1d3e65')
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_ID', formatString('85d4d958-e04b-447c-896c-9c7ff02d8a1a')
|
||||
buildConfigField 'String', 'FRESHCHAT_APP_KEY', formatString('f829aae8-5aa7-4d40-8355-180c6459472a')
|
||||
}
|
||||
}
|
||||
packagingOptions {
|
||||
@@ -328,6 +337,9 @@ dependencies {
|
||||
|
||||
// Digitap for Aadhaar kyc
|
||||
implementation 'com.digitap.sdk:okyc:1.1.4'
|
||||
|
||||
// Freshchat sdk
|
||||
implementation 'com.github.freshdesk:freshchat-android:3.6.4'
|
||||
}
|
||||
|
||||
task executeTestsOnBrowserStack {
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
android:name=".getloan.bankdetailsautodebit.activities.EnachTutorialActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/BaseThemeStyle" />
|
||||
|
||||
|
||||
<activity
|
||||
android:name=".getloan.activities.FaqsActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@@ -262,6 +262,38 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- for freshchat -->
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.naviapp.freshchat.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true"
|
||||
tools:replace="android:authorities">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/freshchat_file_provider_paths"
|
||||
tools:replace="android:resource" />
|
||||
</provider>
|
||||
|
||||
<activity
|
||||
android:name="com.freshchat.consumer.sdk.activity.ChannelListActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/FreshChatStyle"
|
||||
tools:replace="android:theme" />
|
||||
|
||||
<activity
|
||||
android:name="com.freshchat.consumer.sdk.activity.ConversationDetailActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/FreshChatStyle"
|
||||
tools:replace="android:theme" />
|
||||
|
||||
<activity
|
||||
android:name="com.freshchat.consumer.sdk.activity.PictureAttachmentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/FreshChatStyle"
|
||||
tools:replace="android:theme" />
|
||||
<!-- end of freshchat -->
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -359,6 +359,7 @@ class NaviAnalytics private constructor() {
|
||||
fun onShareAppMenuTap() = NaviTrackEvent.trackEvent("share_app_tap")
|
||||
fun onMyLoansMenuTap() = NaviTrackEvent.trackEvent("my_loans_tap")
|
||||
fun onInsuranceMenuTap() = NaviTrackEvent.trackEvent("insurance_tap")
|
||||
fun onChatMenuTap() = NaviTrackEvent.trackEvent("chat_tap")
|
||||
}
|
||||
|
||||
inner class Dashboard {
|
||||
|
||||
39
app/src/main/java/com/naviapp/chat/NaviChatHelper.kt
Normal file
39
app/src/main/java/com/naviapp/chat/NaviChatHelper.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* *
|
||||
* * Copyright (c) 2020 . All rights reserved @Navi
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.chat
|
||||
|
||||
import com.freshchat.consumer.sdk.Freshchat
|
||||
import com.naviapp.app.NaviApplication
|
||||
import com.naviapp.models.UserProfile
|
||||
|
||||
class NaviChatHelper {
|
||||
|
||||
private val chatUtil = NaviChatUtil.instance
|
||||
|
||||
fun initialize() {
|
||||
chatUtil.initConfig()
|
||||
}
|
||||
|
||||
fun setUserData(user: UserProfile?) {
|
||||
chatUtil.setUserData(user)
|
||||
}
|
||||
|
||||
fun setExternalUserId() {
|
||||
chatUtil.setExternalUserId()
|
||||
}
|
||||
|
||||
fun resetUser() {
|
||||
chatUtil.resetUser()
|
||||
}
|
||||
|
||||
fun showConversations() {
|
||||
try {
|
||||
Freshchat.showConversations(NaviApplication.instance.applicationContext)
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
83
app/src/main/java/com/naviapp/chat/NaviChatUtil.kt
Normal file
83
app/src/main/java/com/naviapp/chat/NaviChatUtil.kt
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* *
|
||||
* * Copyright (c) 2020 . All rights reserved @Navi
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.chat
|
||||
|
||||
import com.freshchat.consumer.sdk.Freshchat
|
||||
import com.freshchat.consumer.sdk.FreshchatConfig
|
||||
import com.naviapp.BuildConfig
|
||||
import com.naviapp.app.NaviApplication
|
||||
import com.naviapp.chat.NaviChatUtil.Holder.INSTANCE
|
||||
import com.naviapp.models.UserProfile
|
||||
import com.naviapp.sharedpref.PreferenceManager
|
||||
import com.naviapp.utils.USER_EXTERNAL_ID
|
||||
import com.naviapp.utils.orFalse
|
||||
|
||||
|
||||
class NaviChatUtil {
|
||||
|
||||
private object Holder {
|
||||
val INSTANCE = NaviChatUtil()
|
||||
}
|
||||
|
||||
fun initConfig() {
|
||||
try {
|
||||
val config = FreshchatConfig(
|
||||
BuildConfig.FRESHCHAT_APP_ID,
|
||||
BuildConfig.FRESHCHAT_APP_KEY
|
||||
)
|
||||
config.isCameraCaptureEnabled = true
|
||||
config.isGallerySelectionEnabled = true
|
||||
config.isResponseExpectationEnabled = true
|
||||
config.domain = "https://msdk.in.freshchat.com"
|
||||
Freshchat.getInstance(NaviApplication.instance.applicationContext)
|
||||
.init(config)
|
||||
} catch (e: Exception) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun setUserData(user: UserProfile?) {
|
||||
try {
|
||||
val freshChatUser =
|
||||
Freshchat.getInstance(NaviApplication.instance.applicationContext)
|
||||
.user
|
||||
user?.let {
|
||||
if (it.name?.isNotBlank().orFalse())
|
||||
freshChatUser.firstName = it.name
|
||||
if (it.phoneNumber?.isNotBlank().orFalse())
|
||||
freshChatUser.setPhone("+91", it.phoneNumber)
|
||||
if (it.email?.isNotBlank().orFalse())
|
||||
freshChatUser.email = it.email
|
||||
}
|
||||
Freshchat.getInstance(NaviApplication.instance.applicationContext).user =
|
||||
freshChatUser
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
fun resetUser() {
|
||||
try {
|
||||
Freshchat.resetUser(NaviApplication.instance.applicationContext)
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
fun setExternalUserId() {
|
||||
try {
|
||||
val externalUserId = PreferenceManager.getStringPreference(USER_EXTERNAL_ID)
|
||||
if (!externalUserId.isNullOrBlank())
|
||||
Freshchat.getInstance(NaviApplication.instance.applicationContext)
|
||||
.identifyUser(externalUserId, null)
|
||||
} catch (e: Exception) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val instance: NaviChatUtil by lazy { INSTANCE }
|
||||
}
|
||||
}
|
||||
24
app/src/main/java/com/naviapp/common/customview/TagView.kt
Normal file
24
app/src/main/java/com/naviapp/common/customview/TagView.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.naviapp.common.customview
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.LinearLayout
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.naviapp.R
|
||||
import com.naviapp.databinding.ViewTagBinding
|
||||
|
||||
class TagView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
|
||||
private var binding: ViewTagBinding
|
||||
|
||||
init {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
binding = DataBindingUtil.inflate(inflater, R.layout.view_tag, this, true)
|
||||
}
|
||||
|
||||
fun setNumber(number: String?) {
|
||||
number?.let {
|
||||
binding.numberTv.text = it
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.naviapp.R
|
||||
import com.naviapp.analytics.NaviAnalytics
|
||||
import com.naviapp.chat.NaviChatHelper
|
||||
import com.naviapp.common.navigator.ScreenNavigator
|
||||
import com.naviapp.dashboard.listeners.FragmentDetachListener
|
||||
import com.naviapp.dashboard.listeners.FragmentInteractionListener
|
||||
@@ -36,6 +37,7 @@ class DashboardActivity : DashboardBaseActivity(), TabLayout.OnTabSelectedListen
|
||||
private val registrationVM by lazy { ViewModelProvider(this).get(RegistrationVM::class.java) }
|
||||
private val naviAnalyticsEventTracker = NaviAnalytics.naviAnalytics.Dashboard()
|
||||
private var customerSupportEmail: String? = null
|
||||
private val naviChatHelper by lazy { NaviChatHelper() }
|
||||
private var userProfile: UserProfile? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -52,12 +54,14 @@ class DashboardActivity : DashboardBaseActivity(), TabLayout.OnTabSelectedListen
|
||||
sharedVM.loggedOut.observeNonNull(this) {
|
||||
if (!it) return@observeNonNull
|
||||
hideLoader()
|
||||
naviChatHelper.resetUser()
|
||||
deleteCacheAndOpenLoginPage()
|
||||
}
|
||||
sharedVM.userProfile.observeNonNull(this) {
|
||||
userProfile = it
|
||||
binding.dashboardHeader.userTitleTv.visibility = View.VISIBLE
|
||||
binding.dashboardHeader.userNameTv.text = populateHomePageUserName(it.name)
|
||||
naviChatHelper.setUserData(it)
|
||||
}
|
||||
sharedVM.customerSupport.observeNonNull(this) {
|
||||
customerSupportEmail = it.email
|
||||
@@ -115,6 +119,10 @@ class DashboardActivity : DashboardBaseActivity(), TabLayout.OnTabSelectedListen
|
||||
addTab(MENU_SCREEN)
|
||||
sharedVM.fetchUserProfileData()
|
||||
sharedVM.fetchCustomerSupportData()
|
||||
|
||||
// for FreshChat
|
||||
naviChatHelper.initialize()
|
||||
naviChatHelper.setExternalUserId()
|
||||
}
|
||||
|
||||
private fun addTab(screen: String) {
|
||||
@@ -243,6 +251,7 @@ class DashboardActivity : DashboardBaseActivity(), TabLayout.OnTabSelectedListen
|
||||
isResultActivity = false
|
||||
)
|
||||
}
|
||||
CHAT -> naviChatHelper.showConversations()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,5 +336,6 @@ class DashboardActivity : DashboardBaseActivity(), TabLayout.OnTabSelectedListen
|
||||
const val SHARE_APP = "SHARE_APP"
|
||||
const val MY_LOANS = "MY_LOANS"
|
||||
const val INSURANCE = "INSURANCE"
|
||||
const val CHAT = "CHAT"
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,15 @@ class MenuItemsAdapter(
|
||||
private val listener: MenuItemClickListener
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
private var chatIndex: Int? = null
|
||||
|
||||
fun updateChat(showBubbleTag: Boolean = false, unreadCount: String? = null) {
|
||||
chatIndex?.let { chatPosition ->
|
||||
menuItems[chatPosition].showBubbleTag = showBubbleTag
|
||||
menuItems[chatPosition].unreadCount = unreadCount
|
||||
notifyItemChanged(chatPosition)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
|
||||
@@ -74,6 +83,12 @@ class MenuItemsAdapter(
|
||||
binding.menuItemBinder = menuItem
|
||||
if (menuItem.itemTag == CUSTOMER_CARE_CALL) {
|
||||
binding.titleTv.spannableString(menuItem.title, 4, R.color.santas_gray)
|
||||
} else if (menuItem.itemTag == CHAT) {
|
||||
chatIndex = position
|
||||
if (menuItem.showBubbleTag) {
|
||||
binding.tagView.setNumber(menuItem.unreadCount)
|
||||
binding.tagView.visibility = View.VISIBLE
|
||||
} else binding.tagView.visibility = View.GONE
|
||||
}
|
||||
binding.root.setOnClickListener { listener.onItemClick(menuItem.itemTag) }
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package com.naviapp.dashboard.menu.fragments
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.freshchat.consumer.sdk.Freshchat
|
||||
import com.freshchat.consumer.sdk.FreshchatCallbackStatus
|
||||
import com.naviapp.R
|
||||
import com.naviapp.analytics.NaviAnalytics
|
||||
import com.naviapp.common.BaseFragment
|
||||
@@ -37,6 +43,18 @@ class MenuFragment private constructor() : BaseFragment(), MenuItemClickListener
|
||||
}
|
||||
}
|
||||
|
||||
private val unreadCountChangeReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
context?.let {
|
||||
Freshchat.getInstance(it)
|
||||
.getUnreadCountAsync { _: FreshchatCallbackStatus, unreadCount: Int ->
|
||||
updateChatView(unreadCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -52,6 +70,13 @@ class MenuFragment private constructor() : BaseFragment(), MenuItemClickListener
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
context?.let {
|
||||
LocalBroadcastManager.getInstance(it).unregisterReceiver(unreadCountChangeReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initUi() {
|
||||
userProfile = arguments?.getParcelable(KEY_USER_PROFILE)
|
||||
binding.menuRv.adapter = MenuItemsAdapter(
|
||||
@@ -60,6 +85,34 @@ class MenuFragment private constructor() : BaseFragment(), MenuItemClickListener
|
||||
userProfile?.hasInsurance.orFalse()
|
||||
), this
|
||||
)
|
||||
setupFreshChatUnreadCount()
|
||||
}
|
||||
|
||||
private fun setupFreshChatUnreadCount() {
|
||||
activity?.applicationContext?.let { context ->
|
||||
Freshchat.getInstance(context)
|
||||
.getUnreadCountAsync { _, unreadCount ->
|
||||
updateChatView(unreadCount)
|
||||
}
|
||||
val intentFilter =
|
||||
IntentFilter(Freshchat.FRESHCHAT_UNREAD_MESSAGE_COUNT_CHANGED)
|
||||
LocalBroadcastManager.getInstance(context)
|
||||
.registerReceiver(unreadCountChangeReceiver, intentFilter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateChatView(unreadCount: Int) {
|
||||
if (unreadCount > 0) {
|
||||
(binding.menuRv.adapter as MenuItemsAdapter).updateChat(
|
||||
true,
|
||||
unreadCount.toString()
|
||||
)
|
||||
} else {
|
||||
(binding.menuRv.adapter as MenuItemsAdapter).updateChat(
|
||||
false,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemClick(item: String) {
|
||||
@@ -76,6 +129,7 @@ class MenuFragment private constructor() : BaseFragment(), MenuItemClickListener
|
||||
SHARE_APP -> doShareApp()
|
||||
MY_LOANS -> doOnMyLoans()
|
||||
INSURANCE -> doOnInsurance()
|
||||
CHAT -> doOnChat()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +200,11 @@ class MenuFragment private constructor() : BaseFragment(), MenuItemClickListener
|
||||
listener?.onActivityCompleted(DashboardActivity.INSURANCE)
|
||||
}
|
||||
|
||||
private fun doOnChat() {
|
||||
naviAnalyticsEventTracker.onChatMenuTap()
|
||||
listener?.onActivityCompleted(DashboardActivity.CHAT)
|
||||
}
|
||||
|
||||
override val screenName: String
|
||||
get() = NaviAnalytics.MENU
|
||||
}
|
||||
|
||||
@@ -6,4 +6,7 @@ data class MenuItemBinder(
|
||||
val icon: Drawable? = null,
|
||||
val title: String? = null,
|
||||
val itemTag: String
|
||||
)
|
||||
) {
|
||||
var showBubbleTag: Boolean = false
|
||||
var unreadCount: String? = null
|
||||
}
|
||||
@@ -36,6 +36,11 @@ fun getMenuItems(hasInsurance: Boolean): List<MenuItemBinder> {
|
||||
application.getString(R.string.faqs),
|
||||
FAQ
|
||||
),
|
||||
MenuItemBinder(
|
||||
application.getDrawable(R.drawable.ic_menu_chat),
|
||||
application.getString(R.string.menu_chat),
|
||||
CHAT
|
||||
),
|
||||
MenuItemBinder(
|
||||
application.getDrawable(R.drawable.ic_menu_email_svg),
|
||||
application.getString(R.string.send_email),
|
||||
@@ -153,6 +158,7 @@ const val SHARE_APP = "share_app"
|
||||
const val MY_LOANS = "my_loans"
|
||||
const val INSURANCE = "insurance"
|
||||
const val USER_INFO = "user_info"
|
||||
const val CHAT = "chat"
|
||||
|
||||
const val EMPTY_HEADER = "empty_header"
|
||||
const val APP_VERSION_HEADING = "app_version_heading"
|
||||
|
||||
13
app/src/main/res/drawable/bg_tag_green.xml
Normal file
13
app/src/main/res/drawable/bg_tag_green.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ /**
|
||||
~ * Copyright (c) 2020 . All rights reserved @Navi
|
||||
~ */
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/green" />
|
||||
<corners android:radius="@dimen/layout_dp_20" />
|
||||
|
||||
</shape>
|
||||
BIN
app/src/main/res/drawable/ic_chat_bubble_left.9.png
Normal file
BIN
app/src/main/res/drawable/ic_chat_bubble_left.9.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 403 B |
BIN
app/src/main/res/drawable/ic_chat_bubble_right.9.png
Normal file
BIN
app/src/main/res/drawable/ic_chat_bubble_right.9.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 449 B |
77
app/src/main/res/drawable/ic_chat_navi_round.xml
Normal file
77
app/src/main/res/drawable/ic_chat_navi_round.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="38dp"
|
||||
android:height="38dp"
|
||||
android:viewportWidth="38"
|
||||
android:viewportHeight="38">
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M19,19m-18,0a18,18 0,1 1,36 0a18,18 0,1 1,-36 0"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#A3A3AB"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M23.3337,11.125H14.688C12.7283,11.125 11.125,12.7316 11.125,14.6951V14.8487C11.125,16.8123 12.7283,18.4188 14.688,18.4188H23.3337C25.2934,18.4188 26.8968,16.8123 26.8968,14.8487V14.6951C26.8968,12.7316 25.2934,11.125 23.3337,11.125Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.7957,15.7999C17.7957,16.183 17.3402,16.4546 16.9305,16.1817L15.4806,14.7299C15.4802,15.1163 15.4798,15.5524 15.4795,15.7964C15.4792,16.0784 15.2499,16.308 14.9682,16.308C14.6864,16.308 14.457,16.0783 14.457,15.7957V13.4854C14.457,13.3453 14.5116,13.2137 14.6107,13.1148C14.7097,13.0159 14.8384,12.9621 14.9812,12.9623C15.1231,12.9629 15.2536,13.0172 15.3514,13.1153L15.4054,13.1693C15.5255,13.2897 15.7328,13.4972 15.9805,13.7453L15.9767,13.749L17.7957,15.5716V15.7999Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.7983,15.1836L16.7812,14.1645L16.7822,13.4677C16.7828,13.1882 17.0101,12.9611 17.2886,12.9611H17.2918C17.5711,12.9611 17.7983,13.1888 17.7983,13.4687V15.1836Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M23.5559,15.8443C23.5559,16.1263 23.3269,16.3557 23.0455,16.3557C22.764,16.3557 22.5352,16.1263 22.5352,15.8444C22.5352,15.6994 22.5352,15.4021 22.5354,15.1026L23.5559,14.0799V15.8443Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M23.5589,13.5303C23.5586,13.5371 23.5569,13.5437 23.5562,13.5504V13.6919L22.5358,14.7143V14.7126C22.0531,15.1965 21.5702,15.6803 21.0869,16.1638C20.9756,16.2754 20.834,16.3353 20.6908,16.3353C20.6463,16.3353 20.6017,16.3295 20.5579,16.3179C20.3784,16.2695 20.2371,16.1283 20.1891,15.9492C20.1403,15.7661 20.1966,15.5713 20.3399,15.4278C21.1257,14.6394 21.9122,13.8512 22.6992,13.0636C22.7747,12.9883 22.8651,12.9471 22.961,12.9447L22.9897,12.9441C23.1433,12.9404 23.2913,13.0022 23.3989,13.112C23.4838,13.1988 23.5376,13.3113 23.5536,13.4304L23.5562,13.4288V13.4503C23.5585,13.4731 23.5599,13.4959 23.5592,13.5189L23.5589,13.5303Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M23.299,19.4222H14.7227C12.7439,19.4222 11.125,21.0444 11.125,23.0271V23.111C11.125,25.0938 12.7439,26.716 14.7227,26.716H23.299C25.2778,26.716 26.8968,25.0938 26.8968,23.111V23.0271C26.8968,21.0444 25.2778,19.4222 23.299,19.4222Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M14.6133,21.9918C14.6133,21.7097 14.8422,21.4803 15.1237,21.4803C15.4049,21.4803 15.6338,21.7095 15.634,21.9913C15.6341,22.1366 15.634,22.434 15.6338,22.7333L14.6133,23.756V21.9918Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.8329,22.4081C17.047,23.1967 16.2603,23.9848 15.4733,24.7725C15.3996,24.8463 15.307,24.8885 15.2124,24.8913L15.1845,24.8919C15.181,24.892 15.1773,24.892 15.1737,24.892C15.0239,24.892 14.8788,24.8311 14.7738,24.7239C14.6887,24.6371 14.6351,24.5245 14.619,24.4055L14.6165,24.4072V24.3857C14.6142,24.3629 14.6128,24.3401 14.6134,24.3171L14.6142,24.2983C14.6144,24.2929 14.616,24.2879 14.6165,24.2827V24.144L15.6368,23.1217V23.1232C16.1195,22.6394 16.6024,22.1556 17.0858,21.6722C17.3084,21.4491 17.6364,21.4411 17.8487,21.6539C18.0588,21.8644 18.052,22.1885 17.8329,22.4081Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M22.3818,24.4189C22.3818,24.7043 22.15,24.9366 21.8652,24.9366H21.8643C21.5795,24.9366 21.3477,24.7043 21.3477,24.4189V22.1093C21.3477,21.8237 21.5795,21.5915 21.8643,21.5915C22.15,21.5915 22.3818,21.8237 22.3818,22.1093V24.4189Z"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.7957,15.7999C17.7957,16.183 17.3402,16.4546 16.9305,16.1817L15.4806,14.7299C15.4802,15.1163 15.4798,15.5524 15.4795,15.7964C15.4792,16.0784 15.2499,16.308 14.9682,16.308C14.6864,16.308 14.457,16.0783 14.457,15.7957V13.4854C14.457,13.3453 14.5116,13.2137 14.6107,13.1148C14.7097,13.0159 14.8384,12.9621 14.9812,12.9623C15.1231,12.9629 15.2536,13.0172 15.3514,13.1153L15.4054,13.1693C15.5255,13.2897 15.7328,13.4972 15.9805,13.7453L15.9767,13.749L17.7957,15.5716V15.7999Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.7983,15.1836L16.7812,14.1645L16.7822,13.4677C16.7828,13.1882 17.0101,12.9611 17.2886,12.9611H17.2918C17.5711,12.9611 17.7983,13.1888 17.7983,13.4687V15.1836Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M23.5559,15.8443C23.5559,16.1263 23.3269,16.3557 23.0455,16.3557C22.764,16.3557 22.5352,16.1263 22.5352,15.8444C22.5352,15.6994 22.5352,15.4021 22.5354,15.1026L23.5559,14.0799V15.8443Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M23.5589,13.5303C23.5586,13.5371 23.5569,13.5437 23.5562,13.5504V13.6919L22.5358,14.7143V14.7126C22.0531,15.1965 21.5702,15.6803 21.0869,16.1638C20.9756,16.2754 20.834,16.3353 20.6908,16.3353C20.6463,16.3353 20.6017,16.3295 20.5579,16.3179C20.3784,16.2695 20.2371,16.1283 20.1891,15.9492C20.1403,15.7661 20.1966,15.5713 20.3399,15.4278C21.1257,14.6394 21.9122,13.8512 22.6992,13.0636C22.7747,12.9883 22.8651,12.9471 22.961,12.9447L22.9897,12.9441C23.1433,12.9404 23.2913,13.0022 23.3989,13.112C23.4838,13.1988 23.5376,13.3113 23.5536,13.4304L23.5562,13.4288V13.4503C23.5585,13.4731 23.5599,13.4959 23.5592,13.5189L23.5589,13.5303Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M14.6133,21.9918C14.6133,21.7097 14.8422,21.4803 15.1237,21.4803C15.4049,21.4803 15.6338,21.7095 15.634,21.9913C15.6341,22.1366 15.634,22.434 15.6338,22.7333L14.6133,23.756V21.9918Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.8329,22.4081C17.047,23.1967 16.2603,23.9848 15.4733,24.7725C15.3996,24.8463 15.307,24.8885 15.2124,24.8913L15.1845,24.8919C15.181,24.892 15.1773,24.892 15.1737,24.892C15.0239,24.892 14.8788,24.8311 14.7738,24.7239C14.6887,24.6371 14.6351,24.5245 14.619,24.4055L14.6165,24.4072V24.3857C14.6142,24.3629 14.6128,24.3401 14.6134,24.3171L14.6142,24.2983C14.6144,24.2929 14.616,24.2879 14.6165,24.2827V24.144L15.6368,23.1217V23.1232C16.1195,22.6394 16.6024,22.1556 17.0858,21.6722C17.3084,21.4491 17.6364,21.4411 17.8487,21.6539C18.0588,21.8644 18.052,22.1885 17.8329,22.4081Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M22.3818,24.4189C22.3818,24.7043 22.15,24.9366 21.8652,24.9366H21.8643C21.5795,24.9366 21.3477,24.7043 21.3477,24.4189V22.1093C21.3477,21.8237 21.5795,21.5915 21.8643,21.5915C22.15,21.5915 22.3818,21.8237 22.3818,22.1093V24.4189Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_chat_send.xml
Normal file
9
app/src/main/res/drawable/ic_chat_send.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M0,7.272L5.438,12.711L16,4L7.289,14.562L12.728,20L20,0L0,7.272Z"
|
||||
android:fillColor="#FF3333"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_menu_chat.xml
Normal file
9
app/src/main/res/drawable/ic_menu_chat.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="18dp"
|
||||
android:height="19dp"
|
||||
android:viewportWidth="18"
|
||||
android:viewportHeight="19">
|
||||
<path
|
||||
android:pathData="M9.168,0.6667C4.5343,0.6667 0.668,4.0578 0.668,8.3467C0.668,12.6355 4.5343,16.0267 9.168,16.0267C9.4622,16.0267 9.7333,15.9674 10.018,15.94V18.6667L11.3278,17.8233C13.1657,16.6391 17.1453,13.5652 17.6198,9.1533C17.6499,8.8909 17.668,8.6221 17.668,8.3467C17.668,4.0578 13.8016,0.6667 9.168,0.6667ZM9.168,2.3733C12.985,2.3733 15.968,5.0954 15.968,8.3467C15.968,8.552 15.9553,8.7568 15.9314,8.9633V8.9667L15.9298,8.97C15.636,11.7012 13.4583,13.8463 11.718,15.245V13.955L10.7003,14.1617C10.2025,14.2626 9.691,14.32 9.168,14.32C5.3509,14.32 2.368,11.5979 2.368,8.3467C2.368,5.0954 5.3509,2.3733 9.168,2.3733ZM4.918,7.4933V9.2H6.618V7.4933H4.918ZM8.318,7.4933V9.2H10.018V7.4933H8.318ZM11.718,7.4933V9.2H13.418V7.4933H11.718Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@@ -30,5 +30,12 @@
|
||||
android:layout_marginStart="@dimen/layout_dp_12"
|
||||
android:text="@{menuItemBinder.title}"
|
||||
tools:text="Your Profile" />
|
||||
|
||||
<com.naviapp.common.customview.TagView
|
||||
android:id="@+id/tag_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/layout_dp_4"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
15
app/src/main/res/layout/view_tag.xml
Normal file
15
app/src/main/res/layout/view_tag.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/number_tv"
|
||||
style="@style/caption_font_style"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_tag_green"
|
||||
android:paddingStart="@dimen/layout_dp_4"
|
||||
android:paddingEnd="@dimen/layout_dp_4"
|
||||
android:textColor="@color/white"
|
||||
tools:text="28" />
|
||||
</layout>
|
||||
@@ -3,6 +3,8 @@
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
|
||||
|
||||
<color name="red">#FF3333</color>
|
||||
<color name="white">#ffffff</color>
|
||||
<color name="black">#000000</color>
|
||||
@@ -84,4 +86,5 @@
|
||||
<color name="yellow">#F7B500</color>
|
||||
<color name="white_60_prc_opc">#99FFFFFF</color>
|
||||
<color name="red_color_2">#EE7765</color>
|
||||
<color name="white_70_prc_opc">#B3FFFFFF</color>
|
||||
</resources>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
<!-- for text sizes -->
|
||||
|
||||
<dimen name="font_extra_mini">8sp</dimen>
|
||||
<dimen name="font_mini">10sp</dimen>
|
||||
<dimen name="font_extra_small">12sp</dimen>
|
||||
<dimen name="font_small">14sp</dimen>
|
||||
@@ -69,6 +70,7 @@
|
||||
<dimen name="card_corner_radius_small">12dp</dimen>
|
||||
|
||||
|
||||
<dimen name="layout_dp_21">21dp</dimen>
|
||||
<dimen name="layout_dp_20">20dp</dimen>
|
||||
<dimen name="layout_dp_32">32dp</dimen>
|
||||
<dimen name="layout_dp_250">250dp</dimen>
|
||||
|
||||
@@ -27,4 +27,7 @@
|
||||
<string name="network_error_installed_app">Installed App Upload Issue</string>
|
||||
|
||||
<string name="digits_for_name">abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
|
||||
|
||||
<string name="freshchat_file_provider_authority">com.naviapp.freshchat.provider</string>
|
||||
|
||||
</resources>
|
||||
@@ -579,4 +579,5 @@
|
||||
<string name="insurance_header">Insurance</string>
|
||||
<string name="accept_terms_of_loan_and_insurance_agreement">I accept the loan agreement and insurance terms</string>
|
||||
<string name="insurance_premium">Insurance Premium</string>
|
||||
<string name="menu_chat">Chat</string>
|
||||
</resources>
|
||||
|
||||
70
app/src/main/res/values/themes.xml
Normal file
70
app/src/main/res/values/themes.xml
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ /**
|
||||
~ * Copyright (c) 2020 . All rights reserved @Navi
|
||||
~ */
|
||||
-->
|
||||
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
|
||||
<style name="FreshChatStyle" parent="Theme.Freshchat.Light">
|
||||
<item name="android:windowBackground">@color/white</item>
|
||||
<item name="colorPrimary">@color/white</item>
|
||||
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
|
||||
<item name="android:statusBarColor">@color/white</item>
|
||||
<item name="android:windowContentTransitions">true</item>
|
||||
<item name="android:homeAsUpIndicator">@drawable/ic_back_arrow_svg</item>
|
||||
<item name="freshchatChannelNameTextStyle">@style/SubheadingExtraSmallFontStyle</item>
|
||||
<item name="freshchatTeamMemberNameTextStyle">@style/ChatTeamMemberNameStyle</item>
|
||||
<item name="freshchatTeamMemberMessageTextStyle">@style/ChatTeamMessageStyle</item>
|
||||
<item name="freshchatTeamMemberMessageTimeTextStyle">@style/ChatTeamMessageTimeStyle</item>
|
||||
<item name="freshchatUserMessageTextStyle">@style/AgreementFontStyle</item>
|
||||
<item name="freshchatUserMessageTimeTextStyle">@style/ExtraSmallTextStyle</item>
|
||||
<item name="freshchatMessageListStyle">@style/ChatTeamBgStyle</item>
|
||||
<item name="freshchatMessageListItemStyle">@style/ChatTeamBgStyle</item>
|
||||
<item name="freshchatTeamMemberAvatarIcon">@drawable/ic_chat_navi_round</item>
|
||||
<item name="freshchatSendIcon">@drawable/ic_chat_send</item>
|
||||
<item name="freshchatChatBubbleLeft">@drawable/ic_chat_bubble_left</item>
|
||||
<item name="freshchatChatBubbleRight">@drawable/ic_chat_bubble_right</item>
|
||||
<item name="freshchatMessageReplyInputViewStyle">@style/ChatMessageReply</item>
|
||||
</style>
|
||||
|
||||
<style name="ChatTeamBgStyle">
|
||||
<item name="android:background">@color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="ChatTeamMessageStyle">
|
||||
<item name="android:fontFamily">@font/navi_semi_bold</item>
|
||||
<item name="android:textSize">@dimen/font_extra_small</item>
|
||||
<item name="android:textColor">@color/white</item>
|
||||
<item name="lineSpacing">@dimen/layout_dp_2</item>
|
||||
<item name="lineHeight">@dimen/layout_dp_20</item>
|
||||
</style>
|
||||
|
||||
<style name="ChatTeamMemberNameStyle">
|
||||
<item name="android:fontFamily">@font/navi_bold</item>
|
||||
<item name="android:textSize">@dimen/font_extra_mini</item>
|
||||
<item name="android:textColor">@color/title_color_one</item>
|
||||
<item name="android:paddingBottom">@dimen/layout_dp_2</item>
|
||||
</style>
|
||||
|
||||
<style name="ChatMessageReply" parent="Widget.Freshchat.MessageReplyEditText">
|
||||
<item name="android:fontFamily">@font/navi_semi_bold</item>
|
||||
<item name="android:textSize">@dimen/font_small</item>
|
||||
<item name="android:textColor">@color/title_color_one</item>
|
||||
</style>
|
||||
|
||||
<style name="ChatTeamMessageTimeStyle" parent="ChatTeamMessageStyle">
|
||||
<item name="android:textSize">@dimen/font_mini</item>
|
||||
<item name="android:textColor">@color/white_70_prc_opc</item>
|
||||
</style>
|
||||
|
||||
<style name="ChatUserMessageStyle">
|
||||
<item name="android:fontFamily">@font/navi_semi_bold</item>
|
||||
<item name="android:textSize">@dimen/font_extra_small</item>
|
||||
<item name="android:textColor">@color/title_color_one</item>
|
||||
<item name="lineHeight">@dimen/layout_dp_20</item>
|
||||
<item name="lineSpacing">@dimen/layout_dp_2</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -9,7 +9,7 @@ buildscript {
|
||||
maven { url 'https://plugins.gradle.org/m2/' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
@@ -48,6 +48,7 @@ allprojects {
|
||||
secretKey "U39PUBib1LoKtyamr58pTvUn2suRb6/if3yp0BLo"
|
||||
}
|
||||
}
|
||||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Thu Apr 30 19:08:01 IST 2020
|
||||
#Tue Aug 25 17:49:33 IST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
||||
|
||||
Reference in New Issue
Block a user