Compare commits

...

3 Commits

Author SHA1 Message Date
d7c0b03a01 fix: 取消上传release目录 2024-12-30 15:43:18 +08:00
1fc2c17cee fix: 取消上传release目录 2024-12-30 15:42:52 +08:00
9258be9522 feat: 新增二维码扫描加好友功能
- 引入华为统一扫码库
- 新增二维码扫描加好友功能
- 优化个人界面的头像显示
- 待修改二维码扫描为自定义界面,目前使用sdk默认界面
- 优化部分工具类
2024-12-30 15:41:05 +08:00
36 changed files with 562 additions and 265 deletions

3
.gitignore vendored
View File

@ -13,4 +13,5 @@
.externalNativeBuild .externalNativeBuild
.cxx .cxx
local.properties local.properties
/app/build /app/build
/app/release

View File

@ -0,0 +1,57 @@
{
"agcgw_all":{
"CN":"connect-drcn.dbankcloud.cn",
"CN_back":"connect-drcn.hispace.hicloud.com",
"DE":"connect-dre.dbankcloud.cn",
"DE_back":"connect-dre.hispace.hicloud.com",
"RU":"connect-drru.hispace.dbankcloud.ru",
"RU_back":"connect-drru.hispace.dbankcloud.cn",
"SG":"connect-dra.dbankcloud.cn",
"SG_back":"connect-dra.hispace.hicloud.com"
},
"websocketgw_all":{
"CN":"connect-ws-drcn.hispace.dbankcloud.cn",
"CN_back":"connect-ws-drcn.hispace.dbankcloud.com",
"DE":"connect-ws-dre.hispace.dbankcloud.cn",
"DE_back":"connect-ws-dre.hispace.dbankcloud.com",
"RU":"connect-ws-drru.hispace.dbankcloud.ru",
"RU_back":"connect-ws-drru.hispace.dbankcloud.cn",
"SG":"connect-ws-dra.hispace.dbankcloud.cn",
"SG_back":"connect-ws-dra.hispace.dbankcloud.com"
},
"client":{
"cp_id":"30086000706675172",
"product_id":"461323198429414855",
"client_id":"1587588378314972480",
"client_secret":"4625B77E16DE4F7BDCBACE964AA0769DD9D9662483352800E7F0C4C0643765D7",
"project_id":"461323198429414855",
"app_id":"113165777",
"api_key":"DQEDAIs/5KZBeWhfKozFIM3eckc6wZ02A0CKy2qOGxjxZAI3Yaz07A3y8TuT0VlF0AuHE0Ozc07Fq76OvItq4OW/Z/nI71mQcbO8VQ==",
"package_name":"com.kaixed.kchat"
},
"oauth_client":{
"client_id":"113165777",
"client_type":1
},
"app_info":{
"app_id":"113165777",
"package_name":"com.kaixed.kchat"
},
"configuration_version":"3.0",
"appInfos":[
{
"package_name":"com.kaixed.kchat",
"client":{
"app_id":"113165777"
},
"app_info":{
"package_name":"com.kaixed.kchat",
"app_id":"113165777"
},
"oauth_client":{
"client_type":1,
"client_id":"113165777"
}
}
]
}

View File

@ -91,10 +91,7 @@ dependencies {
// 自定义spannable // 自定义spannable
implementation(libs.spannable) implementation(libs.spannable)
implementation(libs.scanplus)
// Navigation Component 依赖
implementation("androidx.navigation:navigation-fragment-ktx:2.8.4")
implementation("androidx.navigation:navigation-ui-ktx:2.8.4")
// implementation(libs.therouter) // implementation(libs.therouter)
// ksp(libs.therouter.ksp) // ksp(libs.therouter.ksp)
} }

View File

@ -77,4 +77,15 @@
-dontwarn com.yalantis.ucrop** -dontwarn com.yalantis.ucrop**
-keep class com.yalantis.ucrop** { *; } -keep class com.yalantis.ucrop** { *; }
-keep interface com.yalantis.ucrop** { *; } -keep interface com.yalantis.ucrop** { *; }
# 华为统一扫描
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}

View File

@ -1,10 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA" /> <!-- 文件读取权限Android 12及更低版本申请 -->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" /> <!-- 读存储媒体和文件权限Android 13及更高版本申请 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-feature <uses-feature
android:name="android.hardware.telephony" android:name="android.hardware.telephony"
@ -39,6 +43,12 @@
android:theme="@style/Theme.KChatAndroid" android:theme="@style/Theme.KChatAndroid"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name=".ui.activity.QrCodeActivity"
android:exported="false" />
<activity
android:name=".ui.activity.ScanActivity"
android:exported="false" />
<activity <activity
android:name=".ui.activity.setting.UpdateTelephoneActivity" android:name=".ui.activity.setting.UpdateTelephoneActivity"
android:exported="false" /> android:exported="false" />

View File

@ -1,9 +1,9 @@
package com.kaixed.kchat package com.kaixed.kchat
import android.app.Application import android.app.Application
import com.kaixed.kchat.data.local.box.ObjectBox
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.box.ObjectBox.init import com.kaixed.kchat.utils.ScreenUtils
import com.kaixed.kchat.utils.DensityUtil
import com.tencent.mmkv.MMKV import com.tencent.mmkv.MMKV
import io.objectbox.android.Admin import io.objectbox.android.Admin
@ -13,14 +13,13 @@ import io.objectbox.android.Admin
* @Date: 2024/10/24 17:04 * @Date: 2024/10/24 17:04
*/ */
class App : Application() { class App : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
MMKV.initialize(this) MMKV.initialize(this)
init(this) ObjectBox.init(this)
Admin(getBoxStore()).start(this) Admin(getBoxStore()).start(this)
ScreenUtils.init(this)
DensityUtil.init(this)
} }
} }

View File

@ -5,11 +5,12 @@ import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet
import com.kaixed.kchat.databinding.ActivityContactUpdatesBinding import com.kaixed.kchat.databinding.ActivityContactUpdatesBinding
import com.kaixed.kchat.utils.DensityUtil import com.kaixed.kchat.utils.ScreenUtils
import com.kaixed.kchat.utils.DensityUtil.dpToPx
class ContactUpdatesActivity : AppCompatActivity() { class ContactUpdatesActivity : AppCompatActivity() {
private lateinit var binding: ActivityContactUpdatesBinding private lateinit var binding: ActivityContactUpdatesBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
@ -24,7 +25,7 @@ class ContactUpdatesActivity : AppCompatActivity() {
ConstraintSet.START, ConstraintSet.START,
ConstraintSet.PARENT_ID, ConstraintSet.PARENT_ID,
ConstraintSet.START, ConstraintSet.START,
dpToPx( 10) ScreenUtils.dp2px(10)
) )
constraintSet.connect( constraintSet.connect(
@ -32,7 +33,7 @@ class ContactUpdatesActivity : AppCompatActivity() {
ConstraintSet.START, ConstraintSet.START,
binding.ifvAvatar.id, binding.ifvAvatar.id,
ConstraintSet.END, ConstraintSet.END,
dpToPx( 10) ScreenUtils.dp2px(10)
) )
constraintSet.applyTo(binding.main) constraintSet.applyTo(binding.main)
} }

View File

@ -21,7 +21,8 @@ import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.utils.ConstantsUtil import com.kaixed.kchat.utils.ConstantsUtil
import com.kaixed.kchat.utils.ConstantsUtil.getAvatarUrl import com.kaixed.kchat.utils.ConstantsUtil.getAvatarUrl
import com.kaixed.kchat.utils.ConstantsUtil.getNickName import com.kaixed.kchat.utils.ConstantsUtil.getNickName
import com.kaixed.kchat.utils.DensityUtil.dp2Px import com.kaixed.kchat.utils.ScreenUtils
import com.kaixed.kchat.utils.ScreenUtils.dp2px
import com.kaixed.kchat.utils.TextUtil import com.kaixed.kchat.utils.TextUtil
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -94,7 +95,7 @@ class FriendCircleActivity : BaseActivity<ActivityFriendCircleBinding>() {
setContent() setContent()
binding.clTool.apply { binding.clTool.apply {
updateLayoutParams { updateLayoutParams {
height = ConstantsUtil.getStatusBarHeight() + dp2Px(45) height = ConstantsUtil.getStatusBarHeight() + dp2px(45)
} }
updatePadding( updatePadding(
top = ConstantsUtil.getStatusBarHeight() top = ConstantsUtil.getStatusBarHeight()

View File

@ -17,8 +17,8 @@ import com.kaixed.kchat.databinding.ActivityLoginBinding
import com.kaixed.kchat.ui.base.BaseActivity import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.utils.Constants.KEYBOARD_HEIGHT_RATIO import com.kaixed.kchat.utils.Constants.KEYBOARD_HEIGHT_RATIO
import com.kaixed.kchat.utils.Constants.MMKV_COMMON_DATA import com.kaixed.kchat.utils.Constants.MMKV_COMMON_DATA
import com.kaixed.kchat.utils.DensityUtil.dpToPx
import com.kaixed.kchat.utils.DrawableUtil.createDrawable import com.kaixed.kchat.utils.DrawableUtil.createDrawable
import com.kaixed.kchat.utils.ScreenUtils.dp2px
import com.kaixed.kchat.viewmodel.UserViewModel import com.kaixed.kchat.viewmodel.UserViewModel
import com.tencent.mmkv.MMKV import com.tencent.mmkv.MMKV
@ -171,7 +171,7 @@ class LoginActivity : BaseActivity<ActivityLoginBinding>() {
} else { } else {
Color.parseColor("#E1E1E1") Color.parseColor("#E1E1E1")
}, },
dpToPx(8) dp2px(8)
) )
} }
} }

View File

@ -1,9 +1,12 @@
package com.kaixed.kchat.ui.activity package com.kaixed.kchat.ui.activity
import android.Manifest
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -12,7 +15,11 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.Glide
import com.huawei.hms.hmsscankit.ScanUtil
import com.huawei.hms.ml.scan.HmsScan
import com.kaixed.kchat.R import com.kaixed.kchat.R
import com.kaixed.kchat.data.LocalDatabase
import com.kaixed.kchat.data.event.UnreadEvent import com.kaixed.kchat.data.event.UnreadEvent
import com.kaixed.kchat.data.local.box.ObjectBox.getBox import com.kaixed.kchat.data.local.box.ObjectBox.getBox
import com.kaixed.kchat.data.local.entity.Contact import com.kaixed.kchat.data.local.entity.Contact
@ -23,6 +30,7 @@ import com.kaixed.kchat.ui.fragment.DiscoveryFragment
import com.kaixed.kchat.ui.fragment.HomeFragment import com.kaixed.kchat.ui.fragment.HomeFragment
import com.kaixed.kchat.ui.fragment.MineFragment import com.kaixed.kchat.ui.fragment.MineFragment
import com.kaixed.kchat.ui.widget.LoadingDialogFragment import com.kaixed.kchat.ui.widget.LoadingDialogFragment
import com.kaixed.kchat.utils.ConstantsUtil.getAvatarUrl
import com.kaixed.kchat.utils.ConstantsUtil.getUsername import com.kaixed.kchat.utils.ConstantsUtil.getUsername
import com.kaixed.kchat.utils.ConstantsUtil.isFirstLaunchApp import com.kaixed.kchat.utils.ConstantsUtil.isFirstLaunchApp
import com.kaixed.kchat.viewmodel.ContactViewModel import com.kaixed.kchat.viewmodel.ContactViewModel
@ -82,6 +90,61 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
initViewPager() initViewPager()
setListener() setListener()
preLoad()
}
private fun preLoad() {
Glide.with(this)
.load(getAvatarUrl())
.preload()
}
// 待优化成自定义界面目前使用的华为sdk的默认界面
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != RESULT_OK || data == null) {
return
}
val errorCode =
data.getIntExtra(ScanUtil.RESULT_CODE, ScanUtil.SUCCESS)
if (errorCode == ScanUtil.ERROR_NO_READ_PERMISSION) {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_EXTERNAL_STORAGE
)
}
if (errorCode == ScanUtil.SUCCESS) {
val hmsScan: HmsScan? = data.getParcelableExtra(ScanUtil.RESULT)
hmsScan?.let {
handleResult(it.showResult)
}
}
}
// 处理扫描结果
private fun handleResult(result: String) {
if (result.startsWith("kchat@")) {
val contactId = result.substringAfter("kchat@")
if (contactId == getUsername()) {
startActivity(Intent(this, ContactsDetailActivity::class.java).apply {
putExtra("contactId", contactId)
putExtra("isMine", true)
})
}
if (LocalDatabase.isMyFriend(contactId)) {
startActivity(Intent(this, ContactsDetailActivity::class.java).apply {
putExtra("contactId", contactId)
})
} else {
contactViewModel.searchContact(contactId)
}
} else {
Toast.makeText(this, "暂不支持识别其他内容", Toast.LENGTH_SHORT).show()
}
} }
override fun onDestroy() { override fun onDestroy() {
@ -96,6 +159,17 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
loadingDialogFragment.dismissLoading() loadingDialogFragment.dismissLoading()
} }
} }
contactViewModel.searchContactResult.observe(this@MainActivity) { result ->
result.onSuccess {
Intent(this, ApplyFriendsDetailActivity::class.java).apply {
putExtra("user", it)
}
}
result.onFailure {
toast("暂不支持识别其他内容")
}
}
} }
override fun initData() { override fun initData() {

View File

@ -63,7 +63,9 @@ class ProfileDetailActivity : BaseActivity<ActivityProfileDetailBinding>() {
setListener() setListener()
updateContent(username) updateContent(username)
}
override fun initData() {
getImageLauncher = getImageLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) { if (result.resultCode == RESULT_OK) {
@ -77,10 +79,6 @@ class ProfileDetailActivity : BaseActivity<ActivityProfileDetailBinding>() {
} }
} }
override fun initData() {
}
private fun updateAvatar(uri: Uri) { private fun updateAvatar(uri: Uri) {
val filePath = getPathFromUri(uri) val filePath = getPathFromUri(uri)
@ -165,6 +163,11 @@ class ProfileDetailActivity : BaseActivity<ActivityProfileDetailBinding>() {
Intent(this, RenameActivity::class.java) Intent(this, RenameActivity::class.java)
) )
} }
binding.ciQrcode.setOnClickListener {
startActivity(
Intent(this, QrCodeActivity::class.java)
)
}
} }
override fun onResume() { override fun onResume() {

View File

@ -0,0 +1,60 @@
package com.kaixed.kchat.ui.activity
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
import com.bumptech.glide.Glide
import com.huawei.hms.hmsscankit.ScanUtil
import com.huawei.hms.hmsscankit.WriterException
import com.huawei.hms.ml.scan.HmsBuildBitmapOption
import com.huawei.hms.ml.scan.HmsScan
import com.kaixed.kchat.R
import com.kaixed.kchat.databinding.ActivityQrCodeBinding
import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.utils.ConstantsUtil.getAvatarUrl
import com.kaixed.kchat.utils.ConstantsUtil.getNickName
import com.kaixed.kchat.utils.ConstantsUtil.getUsername
import com.kaixed.kchat.utils.ScreenUtils
class QrCodeActivity : BaseActivity<ActivityQrCodeBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding.ivQrcode.updateLayoutParams {
width = ScreenUtils.getScreenWidth() / 2
height = width
}
}
override fun initData() {
setupQrcode()
binding.tvNickname.text = getNickName()
Glide.with(this).load(getAvatarUrl()).error(R.drawable.ic_default_avatar)
.into(binding.ifvAvatar)
}
private fun setupQrcode() {
val content = "kchat@${getUsername()}"
val type = HmsScan.QRCODE_SCAN_TYPE
val width = ScreenUtils.getScreenWidth() / 2
val bgColor = ContextCompat.getColor(this, R.color.white)
val color = ContextCompat.getColor(this, R.color.white)
val options = HmsBuildBitmapOption.Creator()
.setBitmapColor(Color.parseColor("#468CFE")).setBitmapBackgroundColor(bgColor).create()
try {
val qrBitmap = ScanUtil.buildBitmap(content, type, width, width, options)
binding.ivQrcode.setImageBitmap(qrBitmap)
} catch (e: WriterException) {
Log.e("QrCodeActivity", "WriterException: ${e.message}")
}
}
override fun inflateBinding(): ActivityQrCodeBinding {
return ActivityQrCodeBinding.inflate(layoutInflater)
}
}

View File

@ -5,10 +5,7 @@ import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextPaint
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.View
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -19,8 +16,8 @@ import com.kaixed.kchat.R
import com.kaixed.kchat.data.model.request.RegisterRequest import com.kaixed.kchat.data.model.request.RegisterRequest
import com.kaixed.kchat.databinding.ActivityRegisterBinding import com.kaixed.kchat.databinding.ActivityRegisterBinding
import com.kaixed.kchat.ui.base.BaseActivity import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.utils.DensityUtil.dpToPx
import com.kaixed.kchat.utils.DrawableUtil.createDrawable import com.kaixed.kchat.utils.DrawableUtil.createDrawable
import com.kaixed.kchat.utils.ScreenUtils.dp2px
import com.kaixed.kchat.viewmodel.UserViewModel import com.kaixed.kchat.viewmodel.UserViewModel
class RegisterActivity : BaseActivity<ActivityRegisterBinding>() { class RegisterActivity : BaseActivity<ActivityRegisterBinding>() {
@ -133,7 +130,7 @@ class RegisterActivity : BaseActivity<ActivityRegisterBinding>() {
private fun setContinueButtonState(textColor: Int, backgroundColor: Int) { private fun setContinueButtonState(textColor: Int, backgroundColor: Int) {
binding.tvContinue.setTextColor(textColor) binding.tvContinue.setTextColor(textColor)
binding.tvContinue.background = createDrawable( binding.tvContinue.background = createDrawable(
backgroundColor, dpToPx(8) backgroundColor, dp2px(8)
) )
} }

View File

@ -0,0 +1,100 @@
package com.kaixed.kchat.ui.activity
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.core.app.ActivityCompat
import com.huawei.hms.hmsscankit.ScanUtil
import com.huawei.hms.ml.scan.HmsScan
import com.huawei.hms.ml.scan.HmsScanAnalyzerOptions
import com.kaixed.kchat.databinding.ActivityScanBinding
import com.kaixed.kchat.ui.base.BaseActivity
class ScanActivity : BaseActivity<ActivityScanBinding>() {
companion object {
private const val CAMERA_REQ_CODE = 100
private const val STORAGE_REQ_CODE = 101
const val REQUEST_CODE_SCAN = 0x012
private const val PERMISSIONS_LENGTH = 1
}
private val options by lazy {
HmsScanAnalyzerOptions.Creator().setHmsScanTypes(HmsScan.ALL_SCAN_TYPE).create()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
initPermission()
scan()
}
private fun scan() {
ScanUtil.startScan(this, REQUEST_CODE_SCAN, options)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_SCAN && data != null) {
val errorCode: Int = data.getIntExtra(ScanUtil.RESULT_CODE, ScanUtil.SUCCESS)
if (errorCode == ScanUtil.ERROR_NO_READ_PERMISSION) {
requestPermissions(
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
STORAGE_REQ_CODE
)
}
if (errorCode == ScanUtil.SUCCESS) {
val hmsScan: HmsScan? = data.getParcelableExtra(ScanUtil.RESULT)
hmsScan?.let {
handleResult(it.showResult)
}
}
}
}
private fun handleResult(result: String) {
if (result.startsWith("kchat@")) {
val contactId = result.substringAfter("kchat@")
startActivity(Intent(this, ContactsDetailActivity::class.java).apply {
putExtra("contactId", contactId)
})
finish()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAMERA_REQ_CODE && grantResults.size == PERMISSIONS_LENGTH && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
scan()
}
if (requestCode == STORAGE_REQ_CODE && grantResults.size == PERMISSIONS_LENGTH && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
scan()
}
}
override fun initData() {
}
private fun initPermission() {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE),
CAMERA_REQ_CODE
)
}
override fun inflateBinding(): ActivityScanBinding {
return ActivityScanBinding.inflate(layoutInflater)
}
}

View File

@ -95,7 +95,7 @@ class ChatAdapter(
holder.bindData(singleMessage) holder.bindData(singleMessage)
} }
} }
(holder as? HasTimer)?.let { (holder as? IHasTimer)?.let {
changeTimerVisibility(it.getTimerView(), singleMessage) changeTimerVisibility(it.getTimerView(), singleMessage)
} }
handleLongClick(holder, position, singleMessage) handleLongClick(holder, position, singleMessage)
@ -124,7 +124,7 @@ class ChatAdapter(
MessagesManager.deleteMessage(message.msgLocalId) MessagesManager.deleteMessage(message.msgLocalId)
} }
interface HasTimer { interface IHasTimer {
fun getTimerView(): TextView fun getTimerView(): TextView
} }
@ -140,7 +140,7 @@ class ChatAdapter(
} }
class CustomViewHolder(val binding: ChatRecycleItemCustomNormalBinding) : class CustomViewHolder(val binding: ChatRecycleItemCustomNormalBinding) :
RecyclerView.ViewHolder(binding.root), HasTimer { RecyclerView.ViewHolder(binding.root), IHasTimer {
fun bindData(message: Messages) { fun bindData(message: Messages) {
val sender = message.senderId == getUsername() val sender = message.senderId == getUsername()
@ -168,7 +168,7 @@ class ChatAdapter(
} }
class ImageViewHolder(val binding: ChatRecycleItemImageNormalBinding) : class ImageViewHolder(val binding: ChatRecycleItemImageNormalBinding) :
RecyclerView.ViewHolder(binding.root), HasTimer { RecyclerView.ViewHolder(binding.root), IHasTimer {
fun bindData(message: Messages) { fun bindData(message: Messages) {
val sender = message.senderId == getUsername() val sender = message.senderId == getUsername()
val avatarUrl = if (sender) ConstantsUtil.getAvatarUrl() else message.avatarUrl val avatarUrl = if (sender) ConstantsUtil.getAvatarUrl() else message.avatarUrl

View File

@ -7,8 +7,8 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.kaixed.kchat.data.model.dynamic.FriendCircleItem import com.kaixed.kchat.data.model.dynamic.FriendCircleItem
import com.kaixed.kchat.databinding.ItemFriendCircleBinding import com.kaixed.kchat.databinding.ItemFriendCircleBinding
import com.kaixed.kchat.utils.DensityUtil import com.kaixed.kchat.utils.ScreenUtils.dp2px
import com.kaixed.kchat.utils.DensityUtil.dp2Px import com.kaixed.kchat.utils.ScreenUtils.getScreenWidth
import com.kaixed.kchat.utils.TextUtil import com.kaixed.kchat.utils.TextUtil
/** /**
@ -59,13 +59,13 @@ class FriendCircleAdapter(val context: Context, val items: List<FriendCircleItem
} }
private fun getGridViewHeight(size: Int): Int { private fun getGridViewHeight(size: Int): Int {
val width = DensityUtil.getScreenWidth() val width = getScreenWidth()
return when (size) { return when (size) {
1, 2 -> (width - dp2Px(100)) / 2 1, 2 -> (width - dp2px(100)) / 2
3 -> (width - dp2Px(105)) / 3 3 -> (width - dp2px(105)) / 3
4 -> (width - dp2Px(100)) + dp2Px(5) 4 -> (width - dp2px(100)) + dp2px(5)
5, 6 -> 2 * (width - dp2Px(100)) / 3 + dp2Px(5) 5, 6 -> 2 * (width - dp2px(100)) / 3 + dp2px(5)
else -> 3 * (width - dp2Px(105)) / 3 + 2 * dp2Px(5) else -> 3 * (width - dp2px(105)) / 3 + 2 * dp2px(5)
} }
} }
} }

View File

@ -1,5 +1,6 @@
package com.kaixed.kchat.ui.fragment package com.kaixed.kchat.ui.fragment
import android.Manifest
import android.animation.Animator import android.animation.Animator
import android.animation.AnimatorListenerAdapter import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
@ -8,6 +9,7 @@ import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.os.Build import android.os.Build
@ -19,32 +21,32 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams import android.view.ViewGroup.MarginLayoutParams
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity.BIND_AUTO_CREATE import androidx.appcompat.app.AppCompatActivity.BIND_AUTO_CREATE
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.huawei.hms.hmsscankit.ScanUtil
import com.huawei.hms.ml.scan.HmsScan
import com.huawei.hms.ml.scan.HmsScanAnalyzerOptions
import com.kaixed.kchat.R import com.kaixed.kchat.R
import com.kaixed.kchat.data.local.entity.Conversation import com.kaixed.kchat.data.local.entity.Conversation
import com.kaixed.kchat.data.model.HomeItem import com.kaixed.kchat.data.model.HomeItem
import com.kaixed.kchat.databinding.FragmentHomeBinding import com.kaixed.kchat.databinding.FragmentHomeBinding
import com.kaixed.kchat.manager.ConversationManager import com.kaixed.kchat.manager.ConversationManager
import com.kaixed.kchat.manager.MessagesManager
import com.kaixed.kchat.service.WebSocketService import com.kaixed.kchat.service.WebSocketService
import com.kaixed.kchat.service.WebSocketService.LocalBinder import com.kaixed.kchat.service.WebSocketService.LocalBinder
import com.kaixed.kchat.ui.activity.AddFriendsActivity import com.kaixed.kchat.ui.activity.AddFriendsActivity
import com.kaixed.kchat.ui.activity.FriendCircleActivity import com.kaixed.kchat.ui.activity.FriendCircleActivity
import com.kaixed.kchat.ui.activity.MainActivity import com.kaixed.kchat.ui.activity.MainActivity
import com.kaixed.kchat.ui.activity.SearchActivity import com.kaixed.kchat.ui.activity.SearchActivity
import com.kaixed.kchat.ui.activity.TestActivity
import com.kaixed.kchat.ui.adapter.ConversationAdapter import com.kaixed.kchat.ui.adapter.ConversationAdapter
import com.kaixed.kchat.ui.adapter.MyGridAdapter import com.kaixed.kchat.ui.adapter.MyGridAdapter
import com.kaixed.kchat.ui.base.BaseFragment import com.kaixed.kchat.ui.base.BaseFragment
import com.kaixed.kchat.ui.i.OnDialogFragmentClickListener import com.kaixed.kchat.ui.i.OnDialogFragmentClickListener
import com.kaixed.kchat.ui.i.OnItemListener import com.kaixed.kchat.ui.i.OnItemListener
import com.kaixed.kchat.ui.widget.HomeDialogFragment import com.kaixed.kchat.ui.widget.HomeDialogFragment
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class HomeFragment : BaseFragment<FragmentHomeBinding>(), OnItemListener, class HomeFragment : BaseFragment<FragmentHomeBinding>(), OnItemListener,
OnDialogFragmentClickListener { OnDialogFragmentClickListener {
@ -123,11 +125,52 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(), OnItemListener,
(activity as MainActivity).updatePosition(1) (activity as MainActivity).updatePosition(1)
} }
HomeItems.SCAN -> {
scan()
}
else -> Toast.makeText(requireContext(), "暂未实现", Toast.LENGTH_SHORT).show() else -> Toast.makeText(requireContext(), "暂未实现", Toast.LENGTH_SHORT).show()
} }
} }
} }
companion object {
private const val REQUEST_CODE_SCAN = 0x012
}
private val options by lazy {
HmsScanAnalyzerOptions.Creator().setHmsScanTypes(HmsScan.QRCODE_SCAN_TYPE).create()
}
// 用于权限请求
private val requestPermissionsLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val cameraPermissionGranted = permissions[Manifest.permission.CAMERA] == true
if (cameraPermissionGranted) {
scan()
} else {
Toast.makeText(requireContext(), "没有权限,无法扫描", Toast.LENGTH_SHORT).show()
}
}
private fun scan() {
when {
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
ScanUtil.startScan(activity, REQUEST_CODE_SCAN, options)
}
else -> {
requestPermissionsLauncher.launch(
arrayOf(Manifest.permission.CAMERA)
)
}
}
}
private fun setOnClick() { private fun setOnClick() {
binding.ivSearch.setOnClickListener { binding.ivSearch.setOnClickListener {
val intent = Intent(context, SearchActivity::class.java) val intent = Intent(context, SearchActivity::class.java)

View File

@ -18,6 +18,8 @@ import com.kaixed.kchat.utils.ConstantsUtil.getUsername
class MineFragment : BaseFragment<FragmentMineBinding>() { class MineFragment : BaseFragment<FragmentMineBinding>() {
private var isAdded = false
override fun inflateBinding( override fun inflateBinding(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup? container: ViewGroup?
@ -28,6 +30,17 @@ class MineFragment : BaseFragment<FragmentMineBinding>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.ifvAvatar.viewTreeObserver.addOnGlobalLayoutListener {
context?.let {
isAdded = true
Glide.with(it)
.load(getAvatarUrl())
.placeholder(R.drawable.ic_default_avatar)
.error(R.drawable.ic_default_avatar)
.into(binding.ifvAvatar)
}
}
binding.clProfile.setOnClickListener { binding.clProfile.setOnClickListener {
startActivity(Intent(requireContext(), ProfileDetailActivity::class.java)) startActivity(Intent(requireContext(), ProfileDetailActivity::class.java))
} }
@ -49,10 +62,12 @@ class MineFragment : BaseFragment<FragmentMineBinding>() {
binding.tvNickname.text = nickname binding.tvNickname.text = nickname
val kid = "星联号: ${getUsername()}" val kid = "星联号: ${getUsername()}"
binding.tvId.text = kid binding.tvId.text = kid
if (!isAdded) {
Glide.with(requireContext()).load(getAvatarUrl()) Glide.with(requireContext())
.placeholder(R.drawable.ic_default_avatar) .load(getAvatarUrl())
.error(R.drawable.ic_default_avatar) .placeholder(R.drawable.ic_default_avatar)
.into(binding.ifvAvatar) .error(R.drawable.ic_default_avatar)
.into(binding.ifvAvatar)
}
} }
} }

View File

@ -10,7 +10,7 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.widget.AppCompatEditText import androidx.appcompat.widget.AppCompatEditText
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.kaixed.kchat.R import com.kaixed.kchat.R
import com.kaixed.kchat.utils.DensityUtil.dp2px import com.kaixed.kchat.utils.ScreenUtils
/** /**
* 自定义 EditText 控件用于绘制下划线 * 自定义 EditText 控件用于绘制下划线
@ -29,7 +29,7 @@ class CustomEditText @JvmOverloads constructor(
private val normalLineColor: Int by lazy { Color.parseColor("#E0E0E0") } private val normalLineColor: Int by lazy { Color.parseColor("#E0E0E0") }
// 下划线高度 // 下划线高度
private val lineHeight: Float by lazy { dp2px(1).toFloat() } private val lineHeight: Float by lazy { ScreenUtils.dp2px(1).toFloat() }
// 画笔,用于绘制下划线 // 画笔,用于绘制下划线
private var paint: Paint = Paint().apply { private var paint: Paint = Paint().apply {

View File

@ -37,7 +37,6 @@ class CustomTitleBar @JvmOverloads constructor(
val titleIcon = typedArray.getResourceId(R.styleable.CustomTitleBar_titleIcon, -1) val titleIcon = typedArray.getResourceId(R.styleable.CustomTitleBar_titleIcon, -1)
val btnName = typedArray.getString(R.styleable.CustomTitleBar_btnName) ?: "" val btnName = typedArray.getString(R.styleable.CustomTitleBar_btnName) ?: ""
if (titleIcon != -1) { if (titleIcon != -1) {
binding.ivSetting.visibility = View.VISIBLE binding.ivSetting.visibility = View.VISIBLE
binding.ivSetting.setImageResource(titleIcon) binding.ivSetting.setImageResource(titleIcon)

View File

@ -8,7 +8,7 @@ import android.view.Window
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.kaixed.kchat.databinding.DialogLoadingBinding import com.kaixed.kchat.databinding.DialogLoadingBinding
import com.kaixed.kchat.utils.DensityUtil.dpToPx import com.kaixed.kchat.utils.ScreenUtils.dp2px
class LoadingDialogFragment : DialogFragment() { class LoadingDialogFragment : DialogFragment() {
@ -42,8 +42,8 @@ class LoadingDialogFragment : DialogFragment() {
// 设置对话框的大小 // 设置对话框的大小
val params = binding.root.layoutParams val params = binding.root.layoutParams
params.height = dpToPx(120) params.height = dp2px(120)
params.width = dpToPx(120) params.width = dp2px(120)
binding.root.layoutParams = params binding.root.layoutParams = params
return dialog return dialog

View File

@ -1,45 +0,0 @@
package com.kaixed.kchat.utils
import android.content.Context
import android.util.TypedValue
/**
* @Author: kaixed
* @Date: 2024/10/24 22:07
*/
object DensityUtil {
private lateinit var appContext: Context
fun init(context: Context) {
appContext = context.applicationContext
}
fun getScreenWidth(): Int = appContext.resources.displayMetrics.widthPixels
fun getScreenHeight(): Int = appContext.resources.displayMetrics.heightPixels
fun dpToPx(dp: Int): Int =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
appContext.resources.displayMetrics
).toInt()
fun dp2Px(dp: Int): Int =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
appContext.resources.displayMetrics
).toInt()
fun dp2px(dp: Int): Int =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
appContext.resources.displayMetrics
).toInt()
fun pxToDp(px: Int): Int =
(px / appContext.resources.displayMetrics.density).toInt()
}

View File

@ -9,9 +9,8 @@ import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.PopupWindow import android.widget.PopupWindow
import androidx.core.view.updateMargins import androidx.core.view.updateMargins
import androidx.viewbinding.ViewBinding
import com.kaixed.kchat.databinding.PopwindowsBinding import com.kaixed.kchat.databinding.PopwindowsBinding
import com.kaixed.kchat.utils.DensityUtil.dpToPx import com.kaixed.kchat.utils.ScreenUtils.dp2px
/** /**
* @Author: kaixed * @Author: kaixed
@ -30,8 +29,8 @@ object PopWindowUtil {
} }
// 获取屏幕的总宽度 // 获取屏幕的总宽度
val screenWidth = context.resources.displayMetrics.widthPixels val screenWidth = ScreenUtils.getScreenWidth()
val screenHeight = context.resources.displayMetrics.heightPixels val screenHeight = ScreenUtils.getScreenHeight()
val location = IntArray(2) val location = IntArray(2)
parentView.getLocationOnScreen(location) parentView.getLocationOnScreen(location)
@ -76,19 +75,18 @@ object PopWindowUtil {
xOffset = if (rightEnough) xOffset = if (rightEnough)
(parentWidth - popupWidth) / 2 (parentWidth - popupWidth) / 2
else else
parentWidth - popupWidth + dpToPx(45) parentWidth - popupWidth + dp2px(45)
marginStart = popupWidth - (dpToPx(55) + parentWidth / 2) marginStart = popupWidth - (dp2px(55) + parentWidth / 2)
} else { } else {
leftEnough = (popupWidth / 2) < distanceToLeftEdge leftEnough = (popupWidth / 2) < distanceToLeftEdge
xOffset = if (leftEnough) parentWidth - popupWidth xOffset = if (leftEnough) parentWidth - popupWidth
else -dpToPx(45) else -dp2px(45)
marginStart = dpToPx(35) + parentWidth / 2 marginStart = dp2px(35) + parentWidth / 2
} }
binding.ivArrowDown.layoutParams = binding.ivArrowDown.layoutParams =
(binding.ivArrowUp.layoutParams as LinearLayout.LayoutParams).apply { (binding.ivArrowUp.layoutParams as LinearLayout.LayoutParams).apply {
val enoughSpace = if (isMine) rightEnough else leftEnough val enoughSpace = if (isMine) rightEnough else leftEnough

View File

@ -0,0 +1,27 @@
package com.kaixed.kchat.utils
import android.content.Context
import android.util.TypedValue
/**
* @Author: kaixed
* @Date: 2024/12/29 22:49
*/
object ScreenUtils {
private lateinit var appContext: Context
fun init(context: Context) {
appContext = context
}
fun getScreenWidth(): Int = appContext.resources.displayMetrics.widthPixels
fun getScreenHeight(): Int = appContext.resources.displayMetrics.heightPixels
fun dp2px(dp: Int): Int =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
appContext.resources.displayMetrics
).toInt()
}

View File

@ -1,5 +1,6 @@
package com.kaixed.kchat.utils package com.kaixed.kchat.utils
import com.kaixed.kchat.utils.ScreenUtils.getScreenWidth
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
@ -34,7 +35,7 @@ object TextUtil {
val prefix = it.groupValues[1] // 提取 ! 前的部分 val prefix = it.groupValues[1] // 提取 ! 前的部分
val width = it.groupValues[2].toInt() // 提取 w 的值 val width = it.groupValues[2].toInt() // 提取 w 的值
val height = it.groupValues[3].toInt() // 提取 h 的值 val height = it.groupValues[3].toInt() // 提取 h 的值
val screenWidth = DensityUtil.getScreenWidth() / 2 val screenWidth = getScreenWidth() / 2
// 计算宽高比 // 计算宽高比
val ratio = width.toFloat() / screenWidth.toFloat() val ratio = width.toFloat() / screenWidth.toFloat()

View File

@ -1,41 +0,0 @@
package com.kaixed.kchat.utils
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.drawable.Drawable
import android.text.style.ImageSpan
import android.util.Log
/**
* @Author: kaixed
* @Date: 2024/10/28 15:57
*/
class VerticalAlignImageSpan : ImageSpan {
constructor(d: Drawable?) : super(d!!)
constructor(d: Drawable?, verticalAlignment: Int) : super(d!!, verticalAlignment)
override fun draw(
canvas: Canvas,
text: CharSequence?,
start: Int,
end: Int,
x: Float,
top: Int,
y: Int,
bottom: Int,
paint: Paint
) {
val drawable = drawable
val fontMetrics = paint.fontMetrics
val transY =
((y + fontMetrics.ascent + y + fontMetrics.descent) / 2 - (drawable.bounds.bottom + drawable
.bounds.top) / 2).toInt()
Log.d("VerticalAlignImageSpan", "transY-> $transY")
canvas.save()
canvas.translate(x, transY.toFloat())
drawable.draw(canvas)
canvas.restore()
}
}

View File

@ -6,7 +6,6 @@ import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet
import com.kaixed.kchat.data.local.entity.Messages import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.utils.DensityUtil.dp2Px
/** /**
* @Author: kaixed * @Author: kaixed
@ -40,66 +39,6 @@ object ViewUtil {
constraintSet.applyTo(parentView) constraintSet.applyTo(parentView)
} }
fun changeView(
parentView: ConstraintLayout,
sender: Boolean,
avatarView: View,
contentView: View
) {
// 获取 dp 到 px 的转换值
val margin = dp2Px(10)
Log.d("dp2Px", "Converted value: $margin")
// 创建 ConstraintSet
val constraintSet = ConstraintSet().apply {
clone(parentView)
if (sender) {
// 发送者布局调整:头像右对齐,内容左对齐
connect(
avatarView.id, ConstraintSet.END,
parentView.id, ConstraintSet.END,
margin
)
connect(
contentView.id, ConstraintSet.END,
avatarView.id, ConstraintSet.START,
margin
)
connect(contentView.id, ConstraintSet.TOP, avatarView.id, ConstraintSet.TOP)
connect(contentView.id, ConstraintSet.BOTTOM, avatarView.id, ConstraintSet.BOTTOM)
} else {
// 接收者布局调整:头像左对齐,内容右对齐
connect(
avatarView.id, ConstraintSet.START,
parentView.id, ConstraintSet.START,
margin
)
connect(
contentView.id, ConstraintSet.START,
avatarView.id, ConstraintSet.END,
margin
)
connect(contentView.id, ConstraintSet.TOP, avatarView.id, ConstraintSet.TOP)
connect(contentView.id, ConstraintSet.BOTTOM, avatarView.id, ConstraintSet.BOTTOM)
}
// 确保更新到父布局
applyTo(parentView)
}
// 调试:打印控件的可见性
Log.d("ConstraintDebug", "avatarView visibility: ${avatarView.visibility}")
Log.d("ConstraintDebug", "contentView visibility: ${contentView.visibility}")
// 强制父布局重新绘制,确保布局生效
parentView.post {
constraintSet.applyTo(parentView)
}
}
fun changeTimerVisibility( fun changeTimerVisibility(
tvTimer: TextView, tvTimer: TextView,
singleMessage: Messages singleMessage: Messages

View File

@ -57,6 +57,7 @@
app:itemName="星联号" /> app:itemName="星联号" />
<com.kaixed.kchat.ui.widget.CustomItem <com.kaixed.kchat.ui.widget.CustomItem
android:id="@+id/ci_qrcode"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:iconSize="21dp" app:iconSize="21dp"

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".ui.activity.QrCodeActivity">
<com.kaixed.kchat.ui.widget.CustomTitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:titleIcon="@drawable/ic_more" />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/ifv_avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginBottom="30dp"
app:layout_constraintBottom_toTopOf="@id/iv_qrcode"
app:layout_constraintStart_toStartOf="@id/iv_qrcode"
app:roundPercent="0.2" />
<TextView
android:id="@+id/tv_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@id/tv_address"
app:layout_constraintStart_toEndOf="@id/ifv_avatar"
app:layout_constraintTop_toTopOf="@id/ifv_avatar" />
<TextView
android:id="@+id/tv_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="中国大陆"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/ifv_avatar"
app:layout_constraintStart_toEndOf="@id/ifv_avatar"
app:layout_constraintStart_toStartOf="@id/tv_nickname"
app:layout_constraintTop_toBottomOf="@id/tv_nickname" />
<ImageView
android:id="@+id/iv_qrcode"
android:layout_width="200dp"
android:layout_height="200dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:text="扫一扫上面的二维码图案,加我为好友"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="@id/iv_qrcode"
app:layout_constraintStart_toStartOf="@id/iv_qrcode"
app:layout_constraintTop_toBottomOf="@id/iv_qrcode" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.activity.ScanActivity">
<com.kaixed.kchat.ui.widget.CustomTitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/fl_scan_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<TextView
android:id="@+id/tv_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:paddingVertical="15dp"
android:text="账号与安全"
android:textColor="@color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/view"
app:layout_goneMarginTop="0dp" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="15dp"
android:src="@drawable/icon_arrow_right"
app:layout_constraintBottom_toBottomOf="@id/tv_item"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_item" />
<View
android:id="@+id/view_item_decoration"
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#E5E5E5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/tv_item" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -15,5 +15,7 @@ buildscript {
} }
dependencies { dependencies {
classpath(libs.objectbox.gradle.plugin) classpath(libs.objectbox.gradle.plugin)
// classpath("com.android.tools.build:gradle:8.6.0")
classpath(libs.agcp)
} }
} }

View File

@ -1,4 +1,5 @@
[versions] [versions]
agcp = "1.9.1.301"
agp = "8.3.2" agp = "8.3.2"
converterGson = "2.11.0" converterGson = "2.11.0"
emoji2 = "1.5.0" emoji2 = "1.5.0"
@ -23,6 +24,7 @@ pictureselector = "v3.11.2"
pinyin4j = "2.5.1" pinyin4j = "2.5.1"
preference = "1.2.1" preference = "1.2.1"
retrofit = "2.11.0" retrofit = "2.11.0"
scanplus = "2.12.0.301"
spannable = "1.2.7" spannable = "1.2.7"
therouter = "1.2.2" therouter = "1.2.2"
window = "1.3.0" window = "1.3.0"
@ -30,9 +32,9 @@ window = "1.3.0"
kotlin = "1.9.23" kotlin = "1.9.23"
coreKtx = "1.13.1" coreKtx = "1.13.1"
objectbox = "4.0.2" objectbox = "4.0.2"
navigationFragment = "2.8.4"
[libraries] [libraries]
agcp = { module = "com.huawei.agconnect:agcp", version.ref = "agcp" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
compress = { module = "io.github.lucksiege:compress", version.ref = "pictureselector" } compress = { module = "io.github.lucksiege:compress", version.ref = "pictureselector" }
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" } eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" }
@ -44,6 +46,7 @@ pictureselector = { module = "io.github.lucksiege:pictureselector", version.ref
pinyin4j = { module = "com.belerweb:pinyin4j", version.ref = "pinyin4j" } pinyin4j = { module = "com.belerweb:pinyin4j", version.ref = "pinyin4j" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit2-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" } retrofit2-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
scanplus = { module = "com.huawei.hms:scanplus", version.ref = "scanplus" }
spannable = { module = "com.github.liangjingkanji:spannable", version.ref = "spannable" } spannable = { module = "com.github.liangjingkanji:spannable", version.ref = "spannable" }
therouter-ksp = { module = "cn.therouter:apt", version.ref = "therouter" } therouter-ksp = { module = "cn.therouter:apt", version.ref = "therouter" }
objectbox-android-objectbrowser = { group = "io.objectbox", name = "objectbox-android-objectbrowser", version.ref = "objectbox" } objectbox-android-objectbrowser = { group = "io.objectbox", name = "objectbox-android-objectbrowser", version.ref = "objectbox" }
@ -67,7 +70,6 @@ preference = { module = "androidx.preference:preference", version.ref = "prefere
therouter = { module = "cn.therouter:router", version.ref = "therouter" } therouter = { module = "cn.therouter:router", version.ref = "therouter" }
ucrop = { module = "io.github.lucksiege:ucrop", version.ref = "pictureselector" } ucrop = { module = "io.github.lucksiege:ucrop", version.ref = "pictureselector" }
window = { module = "androidx.window:window", version.ref = "window" } window = { module = "androidx.window:window", version.ref = "window" }
androidx-navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" }
[plugins] [plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" } androidApplication = { id = "com.android.application", version.ref = "agp" }

View File

@ -1,6 +1,6 @@
#Fri May 03 23:21:48 CST 2024 #Mon Dec 30 11:12:59 CST 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

BIN
kchat.jks Normal file

Binary file not shown.

View File

@ -9,6 +9,7 @@ pluginManagement {
} }
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
maven(url = "https://developer.huawei.com/repo/")
} }
} }
dependencyResolutionManagement { dependencyResolutionManagement {
@ -16,9 +17,8 @@ dependencyResolutionManagement {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven { maven { url = uri("https://jitpack.io") }
url = uri("https://jitpack.io") maven(url = "https://developer.huawei.com/repo/")
}
} }
} }