diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..b78af99 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +KChat-Android \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b589d56..b86273d 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 0897082..7b3006b 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,6 +4,7 @@ diff --git a/README.md b/README.md index a808eb0..59e3664 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ - [x] **搜索功能**:支持通过关键词在聊天记录中搜索消息,同时支持按文件类型筛选。 - [x] **修改个人信息**:用户可以修改昵称、头像、个性签名等个人信息,提升个性化体验。 - [x] **修改用户密码**:用户可以更新自己的密码。 +- [x] **离线消息**:即使用户离线,服务器也会缓存消息,并在用户上线后自动同步到设备。 - [ ] **查看好友动态**:支持查看好友分享的动态内容,形式包括文字、图片和视频,用户可以点赞或评论。 - [ ] **支持多媒体消息**:支持发送音频、视频、文件等多种格式,满足用户不同的交流需求。 - [ ] **群聊支持**:用户可以创建群组,与多人实时互动,并支持群管理功能(如设置群管理员、踢人)。 - [ ] **消息通知**:支持推送通知,提醒用户有新的消息,未读消息可在通知栏中展示摘要。 -- [ ] **离线消息**:即使用户离线,服务器也会缓存消息,并在用户上线后自动同步到设备。 ### 其他特性 -- [ ] **消息加密**:所有用户消息在传输过程中都进行端到端加密,确保通信安全,防止信息泄露。 +- [x] **消息加密**:所有用户消息在传输过程中都进行端到端加密,确保通信安全,防止信息泄露。 - [ ] **个性化设置**:支持用户自定义头像、昵称、聊天背景,提供多种预设主题和自定义选项。 - [ ] **深色/浅色模式**:支持自动或手动切换界面主题,适配不同的光线环境和用户偏好。 diff --git a/app/src/main/kotlin/com/kaixed/kchat/extensions/CommonExtensions.kt b/app/src/main/kotlin/com/kaixed/kchat/extensions/CommonExtensions.kt new file mode 100644 index 0000000..58cf6d1 --- /dev/null +++ b/app/src/main/kotlin/com/kaixed/kchat/extensions/CommonExtensions.kt @@ -0,0 +1,19 @@ +package com.kaixed.kchat.extensions + +import android.content.Intent +import android.os.Build +import android.os.Parcelable + +/** + * @Author: kaixed + * @Date: 2025/1/26 19:41 + */ +// 扩展函数,用于兼容不同版本的 Intent.getParcelableExtra 方法 +inline fun Intent.getParcelableExtraCompat(key: String): T? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + getParcelableExtra(key, T::class.java) + } else { + @Suppress("DEPRECATION") + getParcelableExtra(key) + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/network/NetworkInterface.kt b/app/src/main/kotlin/com/kaixed/kchat/network/NetworkInterface.kt index 5c4a970..dc05114 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/network/NetworkInterface.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/network/NetworkInterface.kt @@ -13,22 +13,43 @@ object NetworkInterface { const val SERVER_URL = "http://$URL" const val WEBSOCKET_SERVER_URL = "ws://$URL" const val WEBSOCKET = "/websocket/single/" - const val USER_INFO = "/users/info/" - const val USER_LOGIN_BY_USERNAME = "/users/login/username" - const val USER_LOGIN_BY_TELEPHONE = "/users/login/telephone" - const val USER_REGISTER = "/users/register" - const val USER_MESSAGES_COUNT = "/users/%s/%s/msgCounts" - const val USER_MESSAGES = "/users/%s/%s/messages" - const val MESSAGE_WITHDRAW = "/messages/" + // 获取access-token + const val ACCESS_TOKEN = "auth/access-token" + // 获取refresh-token + const val REFRESH_TOKEN = "auth/refresh-token" + // 登录接口(根据用户名登录) + const val LOGIN_BY_USERNAME = "auth/login/username" + // 登录接口(根据电话登录) + const val LOGIN_BY_TELEPHONE = "auth/login/telephone" + // 注册接口 + const val REGISTER = "auth/register" - const val USER_LIST = "/users/list/" + // 上传文件 + const val UPLOAD_FILE = "file/upload" - const val ADD_FRIEND = "/friend/request" - const val FRIEND_LIST = "/friend/list" - const val FRIEND_REQUEST_LIST = "/friend/request/list" - const val ACCEPT_CONTACT_REQUEST = "/friend/accept" + // 更新用户密码 + const val UPDATE_PASSWORD = "user/password/update" + // 获取用户信息 + const val GET_USER_INFO = "user/info/fetch" + // 更新用户信息 + const val UPDATE_USER_INFO = "user/info/update" + // 上传用户头像 + const val UPLOAD_AVATAR = "user/upload-avatar" - const val UPDATE_USER_INFO = "/users/info" - const val UPLOAD_AVATAR = "/users/avatar" + // 发送好友请求 + const val SEND_FRIEND_REQUEST = "friends/requests/send" + // 接受好友请求 + const val ACCEPT_FRIEND_REQUEST = "friends/requests/accept" + // 获取好友列表 + const val GET_FRIENDS = "friends/list" + // 获取好友请求列表 + const val GET_FRIEND_LIST = "friends/requests/fetch" + // 删除好友 + const val DELETE_FRIEND = "friends/delete-friend" + // 设置好友备注 + const val SET_FRIEND_REMARK = "friends/set-remark" + + //撤回消息 + const val RECALL_MESSAGE = "message/withdraw" } diff --git a/app/src/main/kotlin/com/kaixed/kchat/network/service/AuthApiService.kt b/app/src/main/kotlin/com/kaixed/kchat/network/service/AuthApiService.kt index 59a27ab..7cb9562 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/network/service/AuthApiService.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/network/service/AuthApiService.kt @@ -4,6 +4,11 @@ import com.kaixed.kchat.data.local.entity.UserInfo import com.kaixed.kchat.data.model.request.RegisterRequest import com.kaixed.kchat.data.model.response.register.Register import com.kaixed.kchat.network.ApiResponse +import com.kaixed.kchat.network.NetworkInterface.ACCESS_TOKEN +import com.kaixed.kchat.network.NetworkInterface.LOGIN_BY_TELEPHONE +import com.kaixed.kchat.network.NetworkInterface.LOGIN_BY_USERNAME +import com.kaixed.kchat.network.NetworkInterface.REFRESH_TOKEN +import com.kaixed.kchat.network.NetworkInterface.REGISTER import retrofit2.http.Body import retrofit2.http.Header import retrofit2.http.POST @@ -15,32 +20,32 @@ import retrofit2.http.Query */ interface AuthApiService { - @POST("auth/access-token") + @POST(ACCESS_TOKEN) suspend fun auth( @Header("Authorization") token: String, @Query("username") username: String ): ApiResponse - @POST("auth/refresh-token") + @POST(REFRESH_TOKEN) suspend fun refresh( @Header("Authorization") token: String, @Query("username") username: String ): ApiResponse // 登录接口(根据用户名登录) - @POST("auth/login/username") + @POST(LOGIN_BY_USERNAME) suspend fun loginByUsername( @Body requestParams: Map, ): ApiResponse // 登录接口(根据电话登录) - @POST("auth/login/telephone") + @POST(LOGIN_BY_TELEPHONE) suspend fun loginByTelephone( @Body requestParams: Map, ): ApiResponse // 注册接口 - @POST("auth/register") + @POST(REGISTER) suspend fun register( @Body registerRequest: RegisterRequest ): ApiResponse diff --git a/app/src/main/kotlin/com/kaixed/kchat/network/service/FileApiService.kt b/app/src/main/kotlin/com/kaixed/kchat/network/service/FileApiService.kt index 05b4d29..ed2c5bc 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/network/service/FileApiService.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/network/service/FileApiService.kt @@ -1,6 +1,7 @@ package com.kaixed.kchat.network.service import com.kaixed.kchat.network.ApiResponse +import com.kaixed.kchat.network.NetworkInterface.UPLOAD_FILE import okhttp3.MultipartBody import retrofit2.http.Multipart import retrofit2.http.POST @@ -13,7 +14,7 @@ import retrofit2.http.Part interface FileApiService { @Multipart - @POST("file/upload") + @POST(UPLOAD_FILE) suspend fun uploadFile( @Part file: MultipartBody.Part ): ApiResponse diff --git a/app/src/main/kotlin/com/kaixed/kchat/network/service/FriendApiService.kt b/app/src/main/kotlin/com/kaixed/kchat/network/service/FriendApiService.kt index ac3417a..6580d32 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/network/service/FriendApiService.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/network/service/FriendApiService.kt @@ -4,6 +4,11 @@ import com.kaixed.kchat.data.local.entity.Contact import com.kaixed.kchat.data.model.friend.FriendRequestItem import com.kaixed.kchat.data.model.search.SearchUser import com.kaixed.kchat.network.ApiResponse +import com.kaixed.kchat.network.NetworkInterface.ACCEPT_FRIEND_REQUEST +import com.kaixed.kchat.network.NetworkInterface.DELETE_FRIEND +import com.kaixed.kchat.network.NetworkInterface.GET_FRIEND_LIST +import com.kaixed.kchat.network.NetworkInterface.SEND_FRIEND_REQUEST +import com.kaixed.kchat.network.NetworkInterface.SET_FRIEND_REMARK import retrofit2.http.Body import retrofit2.http.Field import retrofit2.http.FormUrlEncoded @@ -16,16 +21,16 @@ import retrofit2.http.Path * @Date: 2025/1/25 16:38 */ interface FriendApiService { - // 获取联系人请求列表 + // 获取好友请求列表 @FormUrlEncoded - @POST("friend/request/list") + @POST(GET_FRIEND_LIST) suspend fun getContactRequestList( @Field("userId") username: String ): ApiResponse?> - // 接受联系人请求 + // 接受好友请求 @FormUrlEncoded - @POST("friend/accept") + @POST(ACCEPT_FRIEND_REQUEST) suspend fun acceptContactRequest( @Field("requestId") contactId: String, @Field("receiverId") username: String, @@ -34,7 +39,7 @@ interface FriendApiService { // 添加联系人 @FormUrlEncoded - @POST("friend/request") + @POST(SEND_FRIEND_REQUEST) suspend fun addContact( @Field("senderId") senderId: String, @Field("receiverId") receiverId: String, @@ -54,7 +59,7 @@ interface FriendApiService { ): ApiResponse?> // 删除联系人 - @POST("friends/delete") + @POST(DELETE_FRIEND) suspend fun deleteContact( @Field("userId") username: String, @Field("contactId") contactId: String, @@ -62,7 +67,7 @@ interface FriendApiService { // 设置好友备注 @FormUrlEncoded - @POST("friend/remark") + @POST(SET_FRIEND_REMARK) suspend fun setRemark( @Field("userId") userId: String, @Field("contactId") contactId: String, diff --git a/app/src/main/kotlin/com/kaixed/kchat/network/service/UserApiService.kt b/app/src/main/kotlin/com/kaixed/kchat/network/service/UserApiService.kt index 96c2bce..62ce088 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/network/service/UserApiService.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/network/service/UserApiService.kt @@ -5,6 +5,11 @@ import com.kaixed.kchat.data.model.request.UserRequest import com.kaixed.kchat.data.model.response.search.User import com.kaixed.kchat.data.model.search.SearchUser import com.kaixed.kchat.network.ApiResponse +import com.kaixed.kchat.network.NetworkInterface.GET_FRIENDS +import com.kaixed.kchat.network.NetworkInterface.GET_USER_INFO +import com.kaixed.kchat.network.NetworkInterface.UPDATE_PASSWORD +import com.kaixed.kchat.network.NetworkInterface.UPDATE_USER_INFO +import com.kaixed.kchat.network.NetworkInterface.UPLOAD_AVATAR import okhttp3.MultipartBody import retrofit2.http.Body import retrofit2.http.Multipart @@ -18,33 +23,33 @@ import retrofit2.http.Part interface UserApiService { // 获取用户列表 - @POST("friends/list") + @POST(GET_FRIENDS) suspend fun fetchUserList( @Body requestParams: Map ): ApiResponse> // 获取用户信息 - @POST("users/info/fetch") + @POST(GET_USER_INFO) suspend fun getUserInfo( @Body requestParams: Map ): ApiResponse // 更改昵称接口 - @POST("users/info") + @POST(UPDATE_USER_INFO) suspend fun changeNickname( @Body userRequest: UserRequest ): ApiResponse // 上传头像接口 @Multipart - @POST("users/avatar") + @POST(UPLOAD_AVATAR) suspend fun uploadAvatar( @Part("username") username: String, @Part file: MultipartBody.Part ): ApiResponse // 更改密码 - @POST("users/password") + @POST(UPDATE_PASSWORD) suspend fun updatePassword( @Body updatePasswordRequest: UpdatePasswordRequest ): ApiResponse diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/AddFriendsActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/AddFriendsActivity.kt index 1835cd9..ce9ae5d 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/AddFriendsActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/AddFriendsActivity.kt @@ -7,6 +7,13 @@ import androidx.activity.enableEdgeToEdge import com.kaixed.kchat.databinding.ActivityAddFriendsBinding import com.kaixed.kchat.ui.base.BaseActivity +/** + * 该文件包含用于兼容不同 Android 版本的 Intent 获取 Parcelable 数据的扩展函数。 + * 通过扩展函数 getParcelableExtraCompat 解决了低版本和高版本 Android 系统间的差异。 + * + * @author kaixed + * @since 2025年1月26日 + */ class AddFriendsActivity : BaseActivity() { private val context: Context by lazy { this } @@ -18,15 +25,21 @@ class AddFriendsActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - - initView() } override fun initData() { } - private fun initView() { + override fun observeData() { + + } + + override fun setupListeners() { + + } + + override fun initView() { binding.ivBack.setOnClickListener { finish() } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyAddFriendActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyAddFriendActivity.kt index 9b083d9..b2b119d 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyAddFriendActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyAddFriendActivity.kt @@ -21,11 +21,13 @@ class ApplyAddFriendActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - setListener() - observeData() } - private fun observeData() { + override fun initView() { + + } + + override fun observeData() { contactViewModel.addContactResult .observe(this) { result -> result.onSuccess { @@ -36,7 +38,7 @@ class ApplyAddFriendActivity : BaseActivity() { } } - private fun setListener() { + override fun setupListeners() { binding.tvSendApply.setOnClickListener { sendContactRequest(contactId) } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyFriendsDetailActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyFriendsDetailActivity.kt index 55e9895..e128ff4 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyFriendsDetailActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApplyFriendsDetailActivity.kt @@ -12,26 +12,14 @@ import com.kaixed.kchat.ui.base.BaseActivity class ApplyFriendsDetailActivity : BaseActivity() { - override fun inflateBinding(): ActivityApplyFriendsDetailBinding { - return ActivityApplyFriendsDetailBinding.inflate(layoutInflater) - } - private var user: SearchUser? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - - setContent() - setOnClick() } - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - override fun initData() { - user = intent.getParcelableExtra("user", SearchUser::class.java) - } - - private fun setContent() { + override fun initView() { val nickname = user?.nickname val signature = user?.signature val avatarUrl = user?.avatarUrl @@ -43,7 +31,12 @@ class ApplyFriendsDetailActivity : BaseActivity diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApproveDetailActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApproveDetailActivity.kt index 400b44e..01367f1 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApproveDetailActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ApproveDetailActivity.kt @@ -1,63 +1,45 @@ package com.kaixed.kchat.ui.activity import android.content.Intent -import android.os.Build import android.os.Bundle import androidx.activity.enableEdgeToEdge -import androidx.annotation.RequiresApi import com.bumptech.glide.Glide -import com.kaixed.kchat.databinding.ActivityApproveDetailBinding import com.kaixed.kchat.data.model.friend.FriendRequestItem +import com.kaixed.kchat.databinding.ActivityApproveDetailBinding +import com.kaixed.kchat.extensions.getParcelableExtraCompat import com.kaixed.kchat.ui.base.BaseActivity class ApproveDetailActivity : BaseActivity() { private var request: FriendRequestItem? = null - override fun inflateBinding(): ActivityApproveDetailBinding { - return ActivityApproveDetailBinding.inflate(layoutInflater) - } - - @RequiresApi(Build.VERSION_CODES.TIRAMISU) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - - handleIntent(intent) - - setContent() - - setOnClick() } override fun initData() { + request = intent.getParcelableExtraCompat("request") + } + + override fun observeData() { } - private fun handleIntent(intent: Intent) { - request = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - intent.getParcelableExtra("request", FriendRequestItem::class.java) - } else { - @Suppress("DEPRECATION") - intent.getParcelableExtra("request") as? FriendRequestItem + override fun initView() { + request?.let { + val nickname = it.nickname + val signature = it.signature + val avatarUrl = it.avatarUrl + + binding.tvContactName.text = nickname + binding.tvContactSignature.text = signature + binding.tvSignatureContent.text = signature + Glide.with(this).load(avatarUrl).into(binding.ifvAvatar) } } - private fun setContent() { - if (request == null) { - return - } - val nickname = request?.nickname - val signature = request?.signature - val avatarUrl = request?.avatarUrl - - binding.tvContactName.text = nickname - binding.tvContactSignature.text = signature - binding.tvSignatureContent.text = signature - Glide.with(this).load(avatarUrl).into(binding.ifvAvatar) - } - - private fun setOnClick() { + override fun setupListeners() { binding.ctl.setOnSettingClickListener { val intent = Intent(this, DataSettingActivity::class.java) startActivity(intent) @@ -73,4 +55,8 @@ class ApproveDetailActivity : BaseActivity() { ) } } + + override fun inflateBinding(): ActivityApproveDetailBinding { + return ActivityApproveDetailBinding.inflate(layoutInflater) + } } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatActivity.kt index bdec026..1f7cac3 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatActivity.kt @@ -116,13 +116,9 @@ class ChatActivity : BaseActivity(), OnItemClickListener, super.onCreate(savedInstanceState) enableEdgeToEdge() EventBus.getDefault().register(this) - observeLiveData() firstLoadData() - initView() - setListener() bindWebSocketService() setPanelChange() - observeStateFlow() if (isSearchHistory) { val size = MessagesManager.queryHistory(msgLocalId) binding.recycleChatList.smoothScrollToPosition(size - 1) @@ -136,17 +132,6 @@ class ChatActivity : BaseActivity(), OnItemClickListener, } } - private fun observeStateFlow() { - lifecycleScope.launch { - MessagesManager.messages.collect { - chatAdapter?.submitList(it) - binding.recycleChatList.post { - binding.recycleChatList.smoothScrollToPosition(0) - } - } - } - } - private val connection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { val binder = service as LocalBinder @@ -266,7 +251,114 @@ class ChatActivity : BaseActivity(), OnItemClickListener, } } - private fun setListener() { + private fun setupFunctionPanel() { + strings?.add("[委屈]") + val mEmojiAdapter = EmojiAdapter(strings) + mEmojiAdapter.setOnItemClickListener(this) + binding.rvEmoji.adapter = mEmojiAdapter + + val gridLayoutManager = GridLayoutManager(this, 7) + binding.rvEmoji.layoutManager = gridLayoutManager + + val map: MutableMap = mutableMapOf() + + map["相册"] = R.drawable.ic_filled_picture + map["拍摄"] = R.drawable.ic_filled_camera + map["位置"] = R.drawable.ic_filled_location + map["名片"] = R.drawable.ic_filled_personal + map["转账"] = R.drawable.ic_filled_transfer + map["文件"] = R.drawable.ic_folder_filled + map["语音输入"] = R.drawable.ic_filled_voiceinput + map["我的收藏"] = R.drawable.ic_filled_favorites + + val functionItems = mutableListOf() + for (i in map.keys) { + functionItems.add(FunctionItem(i, map[i]!!)) + } + + val functionPanelAdapter = FunctionPanelAdapter(functionItems, this) + functionPanelAdapter.setOnItemClickListener(this) + binding.gvFunctionPanel.adapter = functionPanelAdapter + } + + override fun onItemClick(position: Int) { + runOnUiThread { + val editable = binding.etInput.text + // 获取当前光标位置 + val index = binding.etInput.selectionStart + // 获取将要插入的表情符号 + val emoji = strings!![position] + // 使用 ImageSpanUtil 插入表情符号 + insertEmoji( + context, editable, binding.etInput.textSize.toInt(), emoji, index + ) + // 设置新的光标位置 + binding.etInput.setSelection(index + emoji.length) + } + } + + override fun initView() { + binding.ctb.setUnReadCount(ConversationManager.unReadMsgCount) + setupFunctionPanel() + setRecycleView() + contactNickname?.let { + binding.ctb.setTitleName(contactNickname!!) + } + setPanel() + } + + private fun setPanel() { + val layoutParams = binding.clBottomPanel.layoutParams + layoutParams.height = softKeyboardHeight + binding.clBottomPanel.layoutParams = layoutParams + } + + override fun initData() { + contactId = intent.getStringExtra("contactId").toString() + contactNickname = intent.getStringExtra("contactNickname") + isSearchHistory = intent.getBooleanExtra("isSearchHistory", false) == true + msgLocalId = intent.getLongExtra("msgLocalId", 0) + + binding.ctb.setTitleName(contactNickname!!) + + softKeyboardHeight = getKeyboardHeight() + mmkv.putString(CURRENT_CONTACT_ID, contactId) + } + + private fun setRecycleView() { + val layoutManager = LinearLayoutManager(this) + layoutManager.reverseLayout = true + binding.recycleChatList.layoutManager = layoutManager + chatAdapter = ChatAdapter(this) + binding.recycleChatList.adapter = chatAdapter + } + + private fun firstLoadData() { + MessagesManager.setContactId(contactId) + MessagesManager.firstLoadMessages() + } + + private fun loadMoreMessages() { + MessagesManager.loadMoreMessages() + } + + override fun observeData() { + webSocketService!!.messageLivedata.observe(this) { + it?.let { + handleMsg(it) + } + } + lifecycleScope.launch { + MessagesManager.messages.collect { + chatAdapter?.submitList(it) + binding.recycleChatList.post { + binding.recycleChatList.smoothScrollToPosition(0) + } + } + } + } + + override fun setupListeners() { binding.etInput.setOnClickListener { if (hasSoftInput()){ MMKV.defaultMMKV().encode(KEYBOARD_HEIGHT, max(getSoftInputHeight(), 300)) @@ -324,108 +416,6 @@ class ChatActivity : BaseActivity(), OnItemClickListener, } } - private fun setupFunctionPanel() { - strings?.add("[委屈]") - val mEmojiAdapter = EmojiAdapter(strings) - mEmojiAdapter.setOnItemClickListener(this) - binding.rvEmoji.adapter = mEmojiAdapter - - val gridLayoutManager = GridLayoutManager(this, 7) - binding.rvEmoji.layoutManager = gridLayoutManager - - val map: MutableMap = mutableMapOf() - - map["相册"] = R.drawable.ic_filled_picture - map["拍摄"] = R.drawable.ic_filled_camera - map["位置"] = R.drawable.ic_filled_location - map["名片"] = R.drawable.ic_filled_personal - map["转账"] = R.drawable.ic_filled_transfer - map["文件"] = R.drawable.ic_folder_filled - map["语音输入"] = R.drawable.ic_filled_voiceinput - map["我的收藏"] = R.drawable.ic_filled_favorites - - val functionItems = mutableListOf() - for (i in map.keys) { - functionItems.add(FunctionItem(i, map[i]!!)) - } - - val functionPanelAdapter = FunctionPanelAdapter(functionItems, this) - functionPanelAdapter.setOnItemClickListener(this) - binding.gvFunctionPanel.adapter = functionPanelAdapter - } - - override fun onItemClick(position: Int) { - runOnUiThread { - val editable = binding.etInput.text - // 获取当前光标位置 - val index = binding.etInput.selectionStart - // 获取将要插入的表情符号 - val emoji = strings!![position] - // 使用 ImageSpanUtil 插入表情符号 - insertEmoji( - context, editable, binding.etInput.textSize.toInt(), emoji, index - ) - // 设置新的光标位置 - binding.etInput.setSelection(index + emoji.length) - } - } - - private fun initView() { - binding.ctb.setUnReadCount(ConversationManager.unReadMsgCount) - setupFunctionPanel() - setRecycleView() - contactNickname?.let { - binding.ctb.setTitleName(contactNickname!!) - } - setPanel() - } - - private fun setPanel() { - val layoutParams = binding.clBottomPanel.layoutParams - layoutParams.height = softKeyboardHeight - binding.clBottomPanel.layoutParams = layoutParams - } - - override fun initData() { - contactId = intent.getStringExtra("contactId").toString() - contactNickname = intent.getStringExtra("contactNickname") - isSearchHistory = intent.getBooleanExtra("isSearchHistory", false) == true - msgLocalId = intent.getLongExtra("msgLocalId", 0) - - binding.ctb.setTitleName(contactNickname!!) - - softKeyboardHeight = getKeyboardHeight() - mmkv.putString(CURRENT_CONTACT_ID, contactId) - } - - private fun setRecycleView() { - val layoutManager = LinearLayoutManager(this) - layoutManager.reverseLayout = true - binding.recycleChatList.layoutManager = layoutManager - chatAdapter = ChatAdapter(this) - binding.recycleChatList.adapter = chatAdapter - } - - private fun firstLoadData() { - MessagesManager.setContactId(contactId) - MessagesManager.firstLoadMessages() - } - - private fun loadMoreMessages() { - MessagesManager.loadMoreMessages() - } - - private fun observeLiveData() { - if (webSocketService == null) { - return - } - webSocketService!!.messageLivedata.observe(this) { - it?.let { - handleMsg(it) - } - } - } - private fun handleMsg(messages: Messages) { MessagesManager.receiveMessage(messages) binding.recycleChatList.smoothScrollToPosition(0) diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatDetailActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatDetailActivity.kt index 1907a3b..1a57d03 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatDetailActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ChatDetailActivity.kt @@ -25,13 +25,9 @@ class ChatDetailActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - - initView() - - setListener() } - private fun initView() { + override fun initView() { Glide.with(this).load(contact?.avatarUrl).into(binding.ifvAvatar) binding.tvContactName.text = contact?.remark ?: contact?.nickname } @@ -41,7 +37,11 @@ class ChatDetailActivity : BaseActivity() { binding.ciSetDisturb.setSwitchChecked(contact?.doNotDisturb ?: false) } - private fun setListener() { + override fun observeData() { + + } + + override fun setupListeners() { binding.ciSetDisturb.sbSwitch.setOnCheckedChangeListener(object : SwitchButton.OnCheckedChangeListener { override fun onCheckedChanged(button: SwitchButton, isChecked: Boolean) { diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactPermissionActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactPermissionActivity.kt index 64d14e3..b28dc6c 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactPermissionActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactPermissionActivity.kt @@ -21,7 +21,14 @@ class ContactPermissionActivity : BaseActivity override fun initData() { } - private fun initView() { + override fun observeData() { + } + + override fun setupListeners() { + + } + + override fun initView() { binding.ciChat.setYesSelected(false) } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactRequestListActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactRequestListActivity.kt index 9594ec0..7211b0d 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactRequestListActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactRequestListActivity.kt @@ -13,7 +13,6 @@ import com.kaixed.kchat.viewmodel.ContactViewModel class ContactRequestListActivity : BaseActivity() { - private var items = mutableListOf() private val contactViewModel: ContactViewModel by viewModels() @@ -38,10 +37,19 @@ class ContactRequestListActivity : BaseActivity diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactUpdatesActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactUpdatesActivity.kt index 193585d..2083bee 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactUpdatesActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactUpdatesActivity.kt @@ -5,17 +5,18 @@ import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintSet import com.kaixed.kchat.databinding.ActivityContactUpdatesBinding +import com.kaixed.kchat.ui.base.BaseActivity import com.kaixed.kchat.utils.ScreenUtils -class ContactUpdatesActivity : AppCompatActivity() { +class ContactUpdatesActivity : BaseActivity() { - private lateinit var binding: ActivityContactUpdatesBinding + override fun inflateBinding(): ActivityContactUpdatesBinding { + return ActivityContactUpdatesBinding.inflate(layoutInflater) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - binding = ActivityContactUpdatesBinding.inflate(layoutInflater) - setContentView(binding.root) val constraintSet = ConstraintSet() constraintSet.clone(binding.main) @@ -37,4 +38,16 @@ class ContactUpdatesActivity : AppCompatActivity() { ) constraintSet.applyTo(binding.main) } + + override fun initView() { + } + + override fun initData() { + } + + override fun observeData() { + } + + override fun setupListeners() { + } } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactsDetailActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactsDetailActivity.kt index 1ab2626..d439fb0 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactsDetailActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ContactsDetailActivity.kt @@ -36,16 +36,49 @@ class ContactsDetailActivity : BaseActivity() { super.onCreate(savedInstanceState) enableEdgeToEdge() - setOnListener() - updateContent() } + override fun initView() { + + } + override fun initData() { contactId = intent.getStringExtra("contactId") isMine = intent.getBooleanExtra("isMine", false) } + override fun observeData() { + } + + override fun setupListeners() { + binding.tvSendMessage.setOnClickListener { + startActivity(Intent(this, ChatActivity::class.java).apply { + putExtra("contactId", contactId) + putExtra("contactNickname", contactId) + }) + } + + binding.ciSetRemarkAndLabel.setOnClickListener { + startActivity(Intent(this, SetRemarkAndLabelActivity::class.java).apply { + putExtra("contactId", contactId) + putExtra("contactNickname", contactNickname) + }) + } + + binding.ctb.setOnSettingClickListener { + startActivity(Intent(this, DataSettingActivity::class.java).apply { + putExtra("contactId", contactId) + }) + } + + binding.ciPermission.setOnClickListener { + startActivity( + Intent(this, ContactPermissionActivity::class.java) + ) + } + } + @SuppressLint("SetTextI18n") private fun updateContent() { if (isMine) { @@ -83,34 +116,6 @@ class ContactsDetailActivity : BaseActivity() { updateContent() } - private fun setOnListener() { - binding.tvSendMessage.setOnClickListener { - startActivity(Intent(this, ChatActivity::class.java).apply { - putExtra("contactId", contactId) - putExtra("contactNickname", contactId) - }) - } - - binding.ciSetRemarkAndLabel.setOnClickListener { - startActivity(Intent(this, SetRemarkAndLabelActivity::class.java).apply { - putExtra("contactId", contactId) - putExtra("contactNickname", contactNickname) - }) - } - - binding.ctb.setOnSettingClickListener { - startActivity(Intent(this, DataSettingActivity::class.java).apply { - putExtra("contactId", contactId) - }) - } - - binding.ciPermission.setOnClickListener { - startActivity( - Intent(this, ContactPermissionActivity::class.java) - ) - } - } - private fun getContactInfo(contactId: String): Contact { return DataBase.contactBox .query(Contact_.username.equal(contactId)) diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/DataSettingActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/DataSettingActivity.kt index b478f0c..c5a2b54 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/DataSettingActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/DataSettingActivity.kt @@ -33,10 +33,20 @@ class DataSettingActivity : BaseActivity(), handleIntent(intent) } + override fun initView() { + + } + override fun initData() { } + override fun observeData() { + } + + override fun setupListeners() { + } + private fun handleIntent(intent: Intent) { contactId = intent.getStringExtra("contactId") ?: "" } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/FriendCircleActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/FriendCircleActivity.kt index d7a5ae3..0763716 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/FriendCircleActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/FriendCircleActivity.kt @@ -38,21 +38,21 @@ class FriendCircleActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - - initView() - setListener() - } - - private fun setListener() { - binding.ivBack.setOnClickListener { - finish() - } } override fun initData() { getItems() } + override fun observeData() { + } + + override fun setupListeners() { + binding.ivBack.setOnClickListener { + finish() + } + } + private fun getItems() { val img = listOf( R.drawable.ic_1, @@ -90,7 +90,7 @@ class FriendCircleActivity : BaseActivity() { @SuppressLint("NewApi") - private fun initView() { + override fun initView() { setContent() binding.clTool.apply { updateLayoutParams { diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LaunchActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LaunchActivity.kt index 2544b26..d9ef27f 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LaunchActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LaunchActivity.kt @@ -35,10 +35,19 @@ class LaunchActivity : BaseActivity() { setOnClickListener() } + override fun initView() { + } + override fun initData() { } + override fun observeData() { + } + + override fun setupListeners() { + } + @SuppressLint("DiscouragedApi", "InternalInsetResource") private fun getStatusBarHeight(): Int { var result = 0 diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LoginActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LoginActivity.kt index 76ad3fc..f5a28ca 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LoginActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/LoginActivity.kt @@ -58,7 +58,7 @@ class LoginActivity : BaseActivity() { } } - private fun initView() { + override fun initView() { setupLoginView() } @@ -210,6 +210,11 @@ class LoginActivity : BaseActivity() { } override fun initData() {} + override fun observeData() { + } + + override fun setupListeners() { + } override fun inflateBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/MainActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/MainActivity.kt index 42e20af..b04d076 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/MainActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/MainActivity.kt @@ -180,6 +180,12 @@ class MainActivity : BaseActivity() { } } + override fun observeData() { + } + + override fun setupListeners() { + } + @Subscribe(threadMode = ThreadMode.MAIN) fun onMessageEvent(unreadEvent: UnreadEvent) { val unreadCount = unreadEvent.unreadCount @@ -191,7 +197,7 @@ class MainActivity : BaseActivity() { } - private fun initView() { + override fun initView() { navItems.forEachIndexed { index, navItem -> navItem.container.setOnClickListener { updateSelection(index) diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ProfileDetailActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ProfileDetailActivity.kt index 22603df..7d1acfe 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ProfileDetailActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ProfileDetailActivity.kt @@ -65,6 +65,9 @@ class ProfileDetailActivity : BaseActivity() { updateContent(username) } + override fun initView() { + } + override fun initData() { getImageLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> @@ -79,6 +82,12 @@ class ProfileDetailActivity : BaseActivity() { } } + override fun observeData() { + } + + override fun setupListeners() { + } + private fun updateAvatar(uri: Uri) { val filePath = getPathFromUri(uri) diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/QrCodeActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/QrCodeActivity.kt index e35cef0..81d1c72 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/QrCodeActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/QrCodeActivity.kt @@ -31,6 +31,9 @@ class QrCodeActivity : BaseActivity() { } } + override fun initView() { + } + override fun initData() { setupQrcode() binding.tvNickname.text = getNickName() @@ -38,6 +41,12 @@ class QrCodeActivity : BaseActivity() { .into(binding.ifvAvatar) } + override fun observeData() { + } + + override fun setupListeners() { + } + private fun setupQrcode() { val content = "kchat@${getUsername()}" val type = HmsScan.QRCODE_SCAN_TYPE diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RegisterActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RegisterActivity.kt index 771b509..2c9230f 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RegisterActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RegisterActivity.kt @@ -33,10 +33,6 @@ class RegisterActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - - initView() - - setOnClickListener() } override fun initData() { @@ -53,7 +49,10 @@ class RegisterActivity : BaseActivity() { } } - private fun setOnClickListener() { + override fun observeData() { + } + + override fun setupListeners() { binding.ivClose.setOnClickListener { finish() } @@ -95,7 +94,7 @@ class RegisterActivity : BaseActivity() { } - private fun initView() { + override fun initView() { setupTip() setOnEtChangeListener() } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RenameActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RenameActivity.kt index ea0a00d..531ab92 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RenameActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/RenameActivity.kt @@ -8,8 +8,8 @@ import androidx.activity.viewModels import androidx.core.widget.addTextChangedListener import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore import com.kaixed.kchat.data.local.entity.UserInfo -import com.kaixed.kchat.databinding.ActivityRenameBinding import com.kaixed.kchat.data.model.request.UserRequest +import com.kaixed.kchat.databinding.ActivityRenameBinding import com.kaixed.kchat.ui.base.BaseActivity import com.kaixed.kchat.ui.widget.LoadingDialogFragment import com.kaixed.kchat.utils.ConstantsUtils.getNickName @@ -19,8 +19,6 @@ import io.objectbox.Box class RenameActivity : BaseActivity() { - private val userInfoBox: Box by lazy { getBoxStore().boxFor(UserInfo::class.java) } - private val userViewModel: UserViewModel by viewModels() private var oldNickname: String = "" @@ -56,10 +54,19 @@ class RenameActivity : BaseActivity() { } } + override fun initView() { + } + override fun initData() { oldNickname = getNickName() } + override fun observeData() { + } + + override fun setupListeners() { + } + private fun updateNicknamesByCondition(newNickname: String, username: String) { binding.ctb.setBtnEnable(false) val dialog: LoadingDialogFragment = LoadingDialogFragment.newInstance("正在保存") diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ScanActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ScanActivity.kt index 2128830..7dafe8c 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ScanActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ScanActivity.kt @@ -86,6 +86,15 @@ class ScanActivity : BaseActivity() { } + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } + private fun initPermission() { ActivityCompat.requestPermissions( this, diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchActivity.kt index 3037f47..15dec21 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchActivity.kt @@ -40,13 +40,22 @@ class SearchActivity : BaseActivity() { } + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } + private fun setupViewVisibility(length: Int) { binding.rvSearchResult.visibility = if (length > 0) View.VISIBLE else View.INVISIBLE binding.tvPageSetting.visibility = if (length > 0) View.INVISIBLE else View.VISIBLE } private fun setupRecycleView() { - binding!!.rvSearchResult.edgeEffectFactory = object : EdgeEffectFactory() { + binding.rvSearchResult.edgeEffectFactory = object : EdgeEffectFactory() { override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect { return object : EdgeEffect(view.context) { override fun onPull(deltaDistance: Float, displacement: Float) { diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchChatHistory.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchChatHistory.kt index c9617de..ca6eece 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchChatHistory.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchChatHistory.kt @@ -140,4 +140,13 @@ class SearchChatHistory : BaseActivity() { contactAvatarUrl = intent?.getStringExtra("contactAvatarUrl") ?: "" contactId = intent?.getStringExtra("contactId") ?: "" } + + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchFriendsActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchFriendsActivity.kt index 7ce6bf8..007c814 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchFriendsActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SearchFriendsActivity.kt @@ -132,11 +132,17 @@ class SearchFriendsActivity : BaseActivity() { override fun initData() { } - private fun initView() { + override fun initView() { binding.clFriends.visibility = View.INVISIBLE binding.tvTitle.visibility = View.INVISIBLE } + override fun setupListeners() { + } + + override fun observeData() { + } + private fun searchUser(username: String) { contactViewModel.searchContact(username) } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ServiceDetailActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ServiceDetailActivity.kt index 1f91c60..58fc043 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ServiceDetailActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/ServiceDetailActivity.kt @@ -4,13 +4,28 @@ import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import com.kaixed.kchat.databinding.ActivityServiceDetailBinding +import com.kaixed.kchat.ui.base.BaseActivity + +class ServiceDetailActivity : BaseActivity() { -class ServiceDetailActivity : AppCompatActivity() { - private lateinit var binding: ActivityServiceDetailBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - binding = ActivityServiceDetailBinding.inflate(layoutInflater) - setContentView(binding.root) + } + + override fun initData() { + } + + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } + + override fun inflateBinding(): ActivityServiceDetailBinding { + return ActivityServiceDetailBinding.inflate(layoutInflater) } } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkActivity.kt index 58a0aac..3746075 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkActivity.kt @@ -4,19 +4,28 @@ import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import com.kaixed.kchat.databinding.ActivitySetRemarkBinding +import com.kaixed.kchat.ui.base.BaseActivity -class SetRemarkActivity : AppCompatActivity() { - private lateinit var binding: ActivitySetRemarkBinding +class SetRemarkActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - binding = ActivitySetRemarkBinding.inflate(layoutInflater) - setContentView(binding.root) - - setOnClickListener() } - private fun setOnClickListener() { + override fun initData() { + } + + override fun initView() { + } + + override fun setupListeners() { binding.ivBack.setOnClickListener { finish() } } + + override fun observeData() { + } + + override fun inflateBinding(): ActivitySetRemarkBinding { + return ActivitySetRemarkBinding.inflate(layoutInflater) + } } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkAndLabelActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkAndLabelActivity.kt index d283af2..3abf441 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkAndLabelActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SetRemarkAndLabelActivity.kt @@ -25,10 +25,6 @@ import kotlinx.coroutines.launch class SetRemarkAndLabelActivity : BaseActivity() { - private val contactBox by lazy { - getBoxStore().boxFor(Contact::class.java) - } - private var contactId: String? = null private var hasFocus = false @@ -59,6 +55,15 @@ class SetRemarkAndLabelActivity : BaseActivity remark = contact?.remark ?: contact?.nickname ?: "" } + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } + override fun onResume() { super.onResume() updateContent() diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SettingsActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SettingsActivity.kt index e0b456f..4d04c2d 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SettingsActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/SettingsActivity.kt @@ -140,4 +140,13 @@ class SettingsActivity : BaseActivity(), View.OnClickLis override fun initData() { } + + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/TestActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/TestActivity.kt index 3553000..04d5730 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/TestActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/TestActivity.kt @@ -4,14 +4,8 @@ import android.os.Bundle import android.text.Spannable import android.text.SpannableString import android.text.style.ClickableSpan -import android.text.util.Linkify import android.util.Patterns import android.view.View -import android.webkit.WebChromeClient -import android.webkit.WebResourceRequest -import android.webkit.WebView -import android.webkit.WebViewClient -import android.widget.ProgressBar import android.widget.TextView import androidx.activity.enableEdgeToEdge import com.kaixed.kchat.databinding.ActivityTestBinding @@ -70,4 +64,13 @@ class TestActivity : BaseActivity() { } + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } + } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/WebViewActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/WebViewActivity.kt index 4d74e63..9d629e6 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/WebViewActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/WebViewActivity.kt @@ -57,6 +57,15 @@ class WebViewActivity : BaseActivity() { url = intent.getStringExtra("url") ?: "" } + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } + private fun setupWebView() { // 启用 JavaScript webView.settings.javaScriptEnabled = true diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AboutActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AboutActivity.kt index 48869f4..089d751 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AboutActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AboutActivity.kt @@ -28,4 +28,13 @@ class AboutActivity : BaseActivity() { loadingDialog.showLoading(supportFragmentManager) } } + + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AccountSecurityActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AccountSecurityActivity.kt index a9eb48d..1a53509 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AccountSecurityActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/AccountSecurityActivity.kt @@ -16,16 +16,6 @@ class AccountSecurityActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - - setListener() - } - - private fun setListener() { - binding.ciUpdatePassword.setOnClickListener { - startActivity( - Intent(this, UpdatePasswordActivity::class.java) - ) - } } override fun initData() { @@ -36,4 +26,18 @@ class AccountSecurityActivity : BaseActivity() { binding.ciTelephone.setItemDesc(telephone) } } + + override fun initView() { + } + + override fun setupListeners() { + binding.ciUpdatePassword.setOnClickListener { + startActivity( + Intent(this, UpdatePasswordActivity::class.java) + ) + } + } + + override fun observeData() { + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateKidActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateKidActivity.kt index cdc9e22..2b30f0b 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateKidActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateKidActivity.kt @@ -17,10 +17,18 @@ class UpdateKidActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - setContentView(R.layout.activity_update_kid) } override fun initData() { } + + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt index 4017d72..a27d3dd 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt @@ -83,6 +83,15 @@ class UpdatePasswordActivity : BaseActivity() { addEdittextFilter() } + override fun initView() { + } + + override fun setupListeners() { + } + + override fun observeData() { + } + private val textWatch = object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateTelephoneActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateTelephoneActivity.kt index 59ccbed..b07d54d 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateTelephoneActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/activity/setting/UpdateTelephoneActivity.kt @@ -22,4 +22,16 @@ class UpdateTelephoneActivity : BaseActivity() { override fun initData() { } + + override fun initView() { + TODO("Not yet implemented") + } + + override fun setupListeners() { + TODO("Not yet implemented") + } + + override fun observeData() { + TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/base/BaseActivity.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/base/BaseActivity.kt index 20e0a99..1302f2d 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/base/BaseActivity.kt @@ -14,13 +14,13 @@ abstract class BaseActivity : AppCompatActivity() { protected lateinit var binding: VB - abstract fun inflateBinding(): VB - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = inflateBinding() setContentView(binding.root) initData() + initView() + setupListeners() AppManager.instance.addActivity(this) } @@ -31,6 +31,12 @@ abstract class BaseActivity : AppCompatActivity() { abstract fun initData() + abstract fun initView() + + abstract fun setupListeners() + + abstract fun observeData() + fun toast(msg: String) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() } @@ -38,4 +44,6 @@ abstract class BaseActivity : AppCompatActivity() { fun toast() { Toast.makeText(this, "暂未开发", Toast.LENGTH_SHORT).show() } + + abstract fun inflateBinding(): VB } \ No newline at end of file diff --git a/app/src/main/kotlin/com/kaixed/kchat/ui/widget/CustomItem.kt b/app/src/main/kotlin/com/kaixed/kchat/ui/widget/CustomItem.kt index f9a9c11..72c8a09 100644 --- a/app/src/main/kotlin/com/kaixed/kchat/ui/widget/CustomItem.kt +++ b/app/src/main/kotlin/com/kaixed/kchat/ui/widget/CustomItem.kt @@ -10,6 +10,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import com.bumptech.glide.Glide import com.kaixed.kchat.R import com.kaixed.kchat.databinding.ItemCustomBinding +import com.kaixed.kchat.utils.ImageLoader /** * @Author: kaixed @@ -123,8 +124,7 @@ class CustomItem @JvmOverloads constructor( if (itemIconRound > 0) { binding.ivItemIcon.roundPercent = itemIconRound - Glide.with(context).load(itemIcon) - .into(binding.ivItemIcon) + ImageLoader.loadImage(context, itemIcon, binding.ivItemIcon) } } else { binding.ivItemIcon.visibility = View.GONE diff --git a/app/src/main/kotlin/com/kaixed/kchat/utils/ImageLoader.kt b/app/src/main/kotlin/com/kaixed/kchat/utils/ImageLoader.kt new file mode 100644 index 0000000..c169b13 --- /dev/null +++ b/app/src/main/kotlin/com/kaixed/kchat/utils/ImageLoader.kt @@ -0,0 +1,54 @@ +package com.kaixed.kchat.utils + +import android.content.Context +import android.widget.ImageView +import com.bumptech.glide.Glide +import com.bumptech.glide.request.RequestOptions + +object ImageLoader { + + fun loadImage(context: Context, url: String, imageView: ImageView) { + Glide.with(context) + .load(url) + .into(imageView) + } + + fun loadImage(context: Context, image: Int, imageView: ImageView) { + Glide.with(context) + .load(image) + .into(imageView) + } + + fun loadImageWithPlaceholder(context: Context, url: String, imageView: ImageView, placeholderResId: Int) { + Glide.with(context) + .load(url) + .apply(getDefaultOptions().placeholder(placeholderResId)) + .into(imageView) + } + + fun loadImageWithError(context: Context, url: String, imageView: ImageView, errorResId: Int) { + Glide.with(context) + .load(url) + .apply(getDefaultOptions().error(errorResId)) + .into(imageView) + } + + fun loadImageCircle(context: Context, url: String, imageView: ImageView) { + Glide.with(context) + .load(url) + .apply(getCircleCropOptions()) + .into(imageView) + } + + private fun getDefaultOptions(): RequestOptions { + return RequestOptions() + .centerCrop() // 默认居中裁剪 + .dontAnimate() // 禁止动画(如果不需要) + } + + private fun getCircleCropOptions(): RequestOptions { + return RequestOptions() + .circleCrop() // 圆形裁剪 + .dontAnimate() // 禁止动画 + } +}