fix: 修复用户首次登陆缓存提示框一直存在问题

This commit is contained in:
糕小菜 2024-12-15 16:20:25 +08:00
parent 805db56d55
commit 293fe2c3ef
19 changed files with 331 additions and 241 deletions

View File

@ -39,6 +39,12 @@
android:theme="@style/Theme.KChatAndroid"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".ui.activity.setting.AccountSecurityActivity"
android:exported="false" />
<activity
android:name=".ui.activity.setting.UpdatePasswordActivity"
android:exported="false" />
<activity
android:name=".ui.activity.SearchChatHistory"
android:exported="false" />
@ -49,7 +55,7 @@
android:name=".ui.activity.setting.AboutActivity"
android:exported="false" />
<activity
android:name=".ui.activity.SettingActivity"
android:name=".ui.activity.SettingsActivity"
android:exported="false" />
<activity
android:name=".ui.activity.WebViewActivity"

View File

@ -0,0 +1,23 @@
package com.kaixed.kchat.data
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.data.local.entity.Conversation
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.data.local.entity.UserInfo
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
/**
* @Author: kaixed
* @Date: 2024/12/14 23:06
*/
object DataBase {
val contactBox: Box<Contact> by lazy { getBoxStore().boxFor() }
val messagesBox: Box<Messages> by lazy { getBoxStore().boxFor() }
val conversationBox: Box<Conversation> by lazy { getBoxStore().boxFor() }
val userInfoBox: Box<UserInfo> by lazy { getBoxStore().boxFor() }
}

View File

@ -8,6 +8,7 @@ import com.kaixed.kchat.data.local.entity.Conversation
import com.kaixed.kchat.data.local.entity.Conversation_
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.data.local.entity.Messages_
import com.kaixed.kchat.data.local.entity.UserInfo
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import io.objectbox.query.QueryBuilder
@ -20,9 +21,15 @@ object LocalDatabase {
private val contactBox: Box<Contact> by lazy { getBoxStore().boxFor() }
private val messagesBox: Box<Messages> by lazy { getBox(Messages::class.java) }
private val messagesBox: Box<Messages> by lazy { getBoxStore().boxFor() }
private val conversationBox: Box<Conversation> by lazy { getBox(Conversation::class.java) }
private val conversationBox: Box<Conversation> by lazy { getBoxStore().boxFor() }
private val userInfoBox: Box<UserInfo> by lazy { getBoxStore().boxFor() }
fun saveUserInfo(userInfo: UserInfo) {
userInfoBox.put(userInfo)
}
fun cleanChatHistory(contactId: String) {
messagesBox.query(Messages_.talkerId.equal(contactId)).build().remove()

View File

@ -12,6 +12,7 @@ import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import com.kaixed.kchat.R
import com.kaixed.kchat.data.LocalDatabase
import com.kaixed.kchat.databinding.ActivityLoginBinding
import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.utils.Constants.KEYBOARD_HEIGHT_RATIO
@ -75,6 +76,9 @@ class LoginActivity : BaseActivity<ActivityLoginBinding>() {
}
userViewModel.loginResult.observe(this) { loginResult ->
loginResult.onSuccess {
it?.let {
LocalDatabase.saveUserInfo(it)
}
navigateToMain()
}
loginResult.onFailure {

View File

@ -43,6 +43,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private val navBinding by lazy { binding.bottomNavContainer }
private val loadingDialogFragment by lazy { LoadingDialogFragment.newInstance("同步数据中") }
private val navItems by lazy {
listOf(
NavItem(navBinding.ivHome, navBinding.tvHome),
@ -73,23 +75,25 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
initView()
initViewPager()
setListener()
}
private fun setListener() {
contactViewModel.contactListResult.observe(this@MainActivity) { result ->
result.onSuccess {
contactBox.put(it ?: emptyList())
loadingDialogFragment.dismissLoading()
}
}
}
override fun initData() {
if (isFirstLaunchApp()) {
lifecycleScope.launch(Dispatchers.Main) {
val loadingDialogFragment = LoadingDialogFragment.newInstance("同步数据中")
delay(200)
delay(400)
loadingDialogFragment.showLoading(supportFragmentManager)
contactViewModel.contactListResult.observe(this@MainActivity) { result ->
result.onSuccess {
contactBox.put(it ?: emptyList())
}
}
contactViewModel.loadFriendList(getUsername())
loadingDialogFragment.dismissLoading()
}
}
}

View File

@ -1,22 +0,0 @@
package com.kaixed.kchat.ui.activity
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import com.kaixed.kchat.databinding.ActivitySettingBinding
import com.kaixed.kchat.ui.base.BaseActivity
class SettingActivity : BaseActivity<ActivitySettingBinding>() {
override fun inflateBinding(): ActivitySettingBinding {
return ActivitySettingBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
}
override fun initData() {
}
}

View File

@ -1,30 +1,28 @@
package com.kaixed.kchat.ui.fragment
package com.kaixed.kchat.ui.activity
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.NavOptions
import androidx.navigation.fragment.findNavController
import androidx.activity.enableEdgeToEdge
import com.kaixed.kchat.R
import com.kaixed.kchat.databinding.FragmentSettingsBinding
import com.kaixed.kchat.databinding.ActivitySettingBinding
import com.kaixed.kchat.ui.activity.setting.AboutActivity
import com.kaixed.kchat.ui.base.BaseFragment
import com.kaixed.kchat.ui.activity.setting.AccountSecurityActivity
import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.ui.widget.MyBottomSheetFragment
class SettingsActivity : BaseActivity<ActivitySettingBinding>(), View.OnClickListener {
class SettingsFragment : BaseFragment<FragmentSettingsBinding>(), View.OnClickListener {
override fun inflateBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentSettingsBinding {
return FragmentSettingsBinding.inflate(inflater, container, false)
private val context by lazy { this }
override fun inflateBinding(): ActivitySettingBinding {
return ActivitySettingBinding.inflate(layoutInflater)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setListener()
}
@ -51,15 +49,19 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding>(), View.OnClickLi
override fun onClick(v: View?) {
when (v?.id) {
R.id.item_account_security -> {
val intent = Intent(this, AccountSecurityActivity::class.java)
startActivity(intent)
val navOptions = NavOptions.Builder()
.setEnterAnim(R.anim.push_in_from_right) // 从右侧推入
.setExitAnim(R.anim.push_out_to_left) // 从左侧推出
.setPopEnterAnim(R.anim.push_in_from_left) // 从左侧推入
.setPopExitAnim(R.anim.push_out_to_right) // 从右侧推出
.build()
findNavController().navigate(R.id.action_settings_to_security, null, navOptions)
// val intent = Intent(context, UpdatePasswordActivity::class.java)
//
// val navOptions = NavOptions.Builder()
// .setEnterAnim(R.anim.push_in_from_right) // 从右侧推入
// .setExitAnim(R.anim.push_out_to_left) // 从左侧推出
// .setPopEnterAnim(R.anim.push_in_from_left) // 从左侧推入
// .setPopExitAnim(R.anim.push_out_to_right) // 从右侧推出
// .build()
//
// findNavController().navigate(R.id.action_settings_to_security, null, navOptions)
}
R.id.item_teen_mode -> {
@ -138,11 +140,15 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding>(), View.OnClickLi
R.id.tv_logout -> {
val bottomSheetFragment = MyBottomSheetFragment()
bottomSheetFragment.show(parentFragmentManager, bottomSheetFragment.tag)
bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.tag)
}
else -> {
}
}
}
override fun initData() {
}
}

View File

@ -0,0 +1,22 @@
package com.kaixed.kchat.ui.activity.setting
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import com.kaixed.kchat.R
import com.kaixed.kchat.databinding.ActivityAccountSecurityBinding
import com.kaixed.kchat.ui.base.BaseActivity
class AccountSecurityActivity : BaseActivity<ActivityAccountSecurityBinding>() {
override fun inflateBinding(): ActivityAccountSecurityBinding {
return ActivityAccountSecurityBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
}
override fun initData() {
}
}

View File

@ -0,0 +1,25 @@
package com.kaixed.kchat.ui.activity.setting
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.kaixed.kchat.R
import com.kaixed.kchat.databinding.ActivityUpdatePasswordBinding
import com.kaixed.kchat.ui.base.BaseActivity
class UpdatePasswordActivity : BaseActivity<ActivityUpdatePasswordBinding>() {
override fun inflateBinding(): ActivityUpdatePasswordBinding {
return ActivityUpdatePasswordBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
}
override fun initData() {
}
}

View File

@ -9,7 +9,7 @@ import com.bumptech.glide.Glide
import com.kaixed.kchat.R
import com.kaixed.kchat.databinding.FragmentMineBinding
import com.kaixed.kchat.ui.activity.ProfileDetailActivity
import com.kaixed.kchat.ui.activity.SettingActivity
import com.kaixed.kchat.ui.activity.SettingsActivity
import com.kaixed.kchat.ui.base.BaseFragment
import com.kaixed.kchat.utils.ConstantsUtil
import com.kaixed.kchat.utils.ConstantsUtil.getAvatarUrl
@ -33,7 +33,7 @@ class MineFragment : BaseFragment<FragmentMineBinding>() {
}
binding.ciSetting.setOnClickListener {
startActivity(Intent(requireContext(), SettingActivity::class.java))
startActivity(Intent(requireContext(), SettingsActivity::class.java))
}
binding.ciSetting.setRedTipVisibility(true)
@ -49,6 +49,7 @@ class MineFragment : BaseFragment<FragmentMineBinding>() {
binding.tvNickname.text = nickname
val kid = "kid: ${getUsername()}"
binding.tvId.text = kid
Glide.with(requireContext()).load(getAvatarUrl())
.placeholder(R.drawable.ic_default_avatar)
.error(R.drawable.ic_default_avatar)

View File

@ -1,27 +0,0 @@
package com.kaixed.kchat.ui.fragment.settings
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.kaixed.kchat.databinding.FragmentAccountSecurityBinding
import com.kaixed.kchat.ui.base.BaseFragment
class AccountSecurityFragment : BaseFragment<FragmentAccountSecurityBinding>() {
override fun inflateBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentAccountSecurityBinding {
return FragmentAccountSecurityBinding.inflate(inflater, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.ctbTitleBar.setOnBackClickListener {
findNavController().navigateUp()
}
}
}

View File

@ -1,60 +0,0 @@
package com.kaixed.kchat.ui.fragment.settings
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.kaixed.kchat.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [ChatFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class ChatFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_chat, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment ChatFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
ChatFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}

View File

@ -1,60 +0,0 @@
package com.kaixed.kchat.ui.fragment.settings
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.kaixed.kchat.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [NewMessageFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class NewMessageFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_new_message, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment NewMessageFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
NewMessageFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}

View File

@ -31,7 +31,7 @@ object ConstantsUtil {
fun getAvatarUrl(): String {
val avatarUrl = userSessionMMKV.getString(AVATAR_URL, "") ?: ""
return TextUtil.extractDimensionsAndPrefix(avatarUrl)?.first ?: ""
return TextUtil.extractUrl(avatarUrl)
}
fun getStatusBarHeight(): Int =

View File

@ -11,6 +11,12 @@ import java.util.Locale
*/
object TextUtil {
fun extractUrl(url: String): String {
val regex = "(.*?)!".toRegex()
val matchResult = regex.find(url)
return matchResult?.groups?.get(1)?.value ?: url
}
/**
* URL 中提取图片的宽度和高度
*

View File

@ -4,8 +4,10 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".ui.fragment.settings.AccountSecurityFragment">
tools:context=".ui.activity.setting.AccountSecurityActivity">
<com.kaixed.kchat.ui.widget.CustomTitleBar
android:id="@+id/ctb_title_bar"

View File

@ -1,20 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray"
android:orientation="vertical"
tools:context=".ui.activity.SettingActivity">
android:fitsSystemWindows="true"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
<com.kaixed.kchat.ui.widget.CustomTitleBar
android:id="@+id/custom_title_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
android:layout_height="wrap_content"
app:titleName="设置" />
<com.kaixed.kchat.ui.widget.ReBoundScrollView
android:id="@+id/re_bound_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/scroll_content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_account_security"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemName="账号与安全" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_teen_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin"
app:isBottomDividerVisible="true"
app:itemName="青少年模式" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_care_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemName="关怀模式" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_new_message_notification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin"
app:isBottomDividerVisible="true"
app:itemName="新消息通知" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_chat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:isBottomDividerVisible="true"
app:itemName="聊天" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_device"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:isBottomDividerVisible="true"
app:itemName="设备" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_general"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemName="通用" />
<TextView
android:id="@+id/text_privacy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:paddingTop="10dp"
android:paddingBottom="5dp"
android:text="隐私" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_friend_permission"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:isBottomDividerVisible="true"
app:itemName="朋友权限" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_personal_info_permission"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:isBottomDividerVisible="true"
app:itemName="个人信息与权限" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_personal_info_collection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:isBottomDividerVisible="true"
app:itemName="个人信息收集清单" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_third_party_info_sharing"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemName="第三方信息共享清单" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_plugin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin"
app:isBottomDividerVisible="true"
app:itemName="插件" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_about_kchat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin"
app:isBottomDividerVisible="true"
app:itemName="关于kchat" />
<com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/item_help_feedback"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemName="帮助与反馈" />
<TextView
android:id="@+id/tv_switch_account"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="@dimen/margin"
android:background="@color/white"
android:gravity="center"
android:text="切换账号"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_logout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="@dimen/margin"
android:layout_marginBottom="20dp"
android:background="@color/white"
android:gravity="center"
android:text="退出"
android:textColor="@color/black"
android:textSize="16sp" />
</LinearLayout>
</com.kaixed.kchat.ui.widget.ReBoundScrollView>
</LinearLayout>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".ui.activity.setting.UpdatePasswordActivity">
<com.kaixed.kchat.ui.widget.CustomTitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:btnName="完成"
app:titleName="设置密码" />
<com.kaixed.kchat.ui.widget.ReBoundScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="请设置您的账户密码"/>
</LinearLayout>
</com.kaixed.kchat.ui.widget.ReBoundScrollView>
</LinearLayout>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/firstFragment">
<fragment
android:id="@+id/firstFragment"
android:name="com.kaixed.kchat.ui.fragment.SettingsFragment"
android:label="SettingsFragment"
tools:layout="@layout/fragment_settings">
<action
android:id="@+id/action_settings_to_security"
app:destination="@id/securityFragment" />
</fragment>
<fragment
android:id="@+id/securityFragment"
android:name="com.kaixed.kchat.ui.fragment.settings.AccountSecurityFragment"
android:label="Third Fragment"
tools:layout="@layout/fragment_account_security" />
</navigation>