Skip to content

Commit

Permalink
Feature:
Browse files Browse the repository at this point in the history
  1. SQL历史记录

Fix:
  1. 切换应用时部分命令会重新发送
  2. 保存插件配置后版本显示为0
  • Loading branch information
YuS1aN committed Apr 1, 2024
1 parent b607345 commit 3599c9d
Show file tree
Hide file tree
Showing 26 changed files with 266 additions and 37 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@

或者采用 `Nginx` 等Web服务器进行反向代理

## TODO (新版本适配中)
* SQL历史记录
<img src="https://raw.githubusercontent.com/YuS1aN/zhenxun_bot_android_ui/master/docs/main.png" width="162" height="360" /><img src="https://raw.githubusercontent.com/YuS1aN/zhenxun_bot_android_ui/master/docs/plugin.png" width="162" height="360" /><img src="https://raw.githubusercontent.com/YuS1aN/zhenxun_bot_android_ui/master/docs/db.png" width="162" height="360" /><img src="https://raw.githubusercontent.com/YuS1aN/zhenxun_bot_android_ui/master/docs/edit.png" width="162" height="360" /><img src="https://raw.githubusercontent.com/YuS1aN/zhenxun_bot_android_ui/master/docs/conversation.png" width="162" height="360" /><img src="https://raw.githubusercontent.com/YuS1aN/zhenxun_bot_android_ui/master/docs/menu.png" width="162" height="360" />
6 changes: 4 additions & 2 deletions app/src/main/java/me/kbai/zhenxunui/api/ApiService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import me.kbai.zhenxunui.model.DeleteRemoteFile
import me.kbai.zhenxunui.model.EditRemoteFile
import me.kbai.zhenxunui.model.ExecuteSql
import me.kbai.zhenxunui.model.FriendListItem
import me.kbai.zhenxunui.model.GetSqlLog
import me.kbai.zhenxunui.model.GroupInfo
import me.kbai.zhenxunui.model.GroupListItem
import me.kbai.zhenxunui.model.HandleRequest
Expand All @@ -18,6 +19,7 @@ import me.kbai.zhenxunui.model.RenameRemoteFile
import me.kbai.zhenxunui.model.RequestListResult
import me.kbai.zhenxunui.model.SendMessage
import me.kbai.zhenxunui.model.SqlLog
import me.kbai.zhenxunui.model.SqlLogPage
import me.kbai.zhenxunui.model.TableColumn
import me.kbai.zhenxunui.model.TableListItem
import me.kbai.zhenxunui.model.UpdateGroup
Expand Down Expand Up @@ -118,8 +120,8 @@ interface ApiService {
@GET("database/get_table_column")
suspend fun getTableColumn(@Query("table_name") table: String): ApiResponse<List<TableColumn>>

@GET("database/get_sql_log")
suspend fun getSqlLog(): ApiResponse<List<SqlLog>>
@POST("database/get_sql_log")
suspend fun getSqlLog(@Body getSqlLog: GetSqlLog): ApiResponse<SqlLogPage>

@POST("database/exec_sql")
suspend fun executeSql(@Body sql: ExecuteSql): ApiResponse<List<LinkedHashMap<String, *>>>
Expand Down
10 changes: 1 addition & 9 deletions app/src/main/java/me/kbai/zhenxunui/extends/ApiExtends.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package me.kbai.zhenxunui.extends

import android.app.Application
import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import me.kbai.zhenxunui.repository.Resource
Expand Down Expand Up @@ -40,18 +38,12 @@ suspend fun <T : Resource<*>> Flow<T>.apiCollect(
action.invoke(value)
}

/**
* 要记得在 active state 恢复 button 状态
*/
fun <T : Resource<*>> Flow<T>.launchAndApiCollectIn(
owner: LifecycleOwner,
button: View? = null,
activeState: Lifecycle.State = Lifecycle.State.STARTED,
action: suspend (value: T) -> Unit
) = owner.lifecycleScope.launch {
owner.repeatOnLifecycle(activeState) {
apiCollect(button = button, action = action)
}
apiCollect(button = button, action = action)
}

//fun <T : Resource<*>> Flow<T>.checkToken(
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/me/kbai/zhenxunui/model/GetSqlLog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package me.kbai.zhenxunui.model

data class GetSqlLog(
val index: Int = 1,
val size: Int = 5
) {
companion object {
val DEFAULT = GetSqlLog()
}
}
6 changes: 6 additions & 0 deletions app/src/main/java/me/kbai/zhenxunui/model/SqlLogPage.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package me.kbai.zhenxunui.model

data class SqlLogPage(
val total: Int,
val data: List<SqlLog>
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import me.kbai.zhenxunui.model.ChatMessage
import me.kbai.zhenxunui.model.DeleteRemoteFile
import me.kbai.zhenxunui.model.EditRemoteFile
import me.kbai.zhenxunui.model.ExecuteSql
import me.kbai.zhenxunui.model.GetSqlLog
import me.kbai.zhenxunui.model.HandleRequest
import me.kbai.zhenxunui.model.PluginDetail
import me.kbai.zhenxunui.model.PluginInfo
Expand Down Expand Up @@ -125,6 +126,8 @@ object ApiRepository {

fun executeSql(sql: ExecuteSql) = networkFlow { BotApi.service.executeSql(sql) }

fun getSqlLog() = networkFlow { BotApi.service.getSqlLog(GetSqlLog.DEFAULT) }

fun readDir(path: String) = networkFlow { BotApi.service.readDir(path) }

fun renameFile(file: RemoteFile, newName: String) = networkFlow {
Expand Down
41 changes: 37 additions & 4 deletions app/src/main/java/me/kbai/zhenxunui/ui/db/DbManageFragment.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package me.kbai.zhenxunui.ui.db

import android.annotation.SuppressLint
import android.util.LayoutDirection
import android.view.Gravity
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.viewModels
import me.kbai.zhenxunui.base.BaseFragment
import me.kbai.zhenxunui.databinding.FragmentDbManageBinding
Expand All @@ -11,19 +16,23 @@ import me.kbai.zhenxunui.extends.viewLifecycleScope
import me.kbai.zhenxunui.repository.Resource
import me.kbai.zhenxunui.tool.GlobalToast
import me.kbai.zhenxunui.viewmodel.DbManageViewModel
import me.kbai.zhenxunui.viewmodel.SqlLogViewModel

/**
* @author Sean on 2023/5/30
*/
class DbManageFragment : BaseFragment<FragmentDbManageBinding>() {

private val mViewModel by viewModels<DbManageViewModel>()
private val mSqlLogViewModel by viewModels<SqlLogViewModel>()

override fun getViewBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentDbManageBinding = FragmentDbManageBinding.inflate(inflater, container, false)


@SuppressLint("ClickableViewAccessibility")
override fun initView() = viewBinding.run {
srlRefresh.setOnRefreshListener {
mViewModel.requestTableList()
Expand All @@ -38,13 +47,37 @@ class DbManageFragment : BaseFragment<FragmentDbManageBinding>() {
if (it.data != null) {
SqlResultDialogFragment().show(childFragmentManager)
}

mSqlLogViewModel.requestSqlLog()
}
}
}

override fun onStart() {
super.onStart()
viewBinding.btnSql.isEnabled = true
etSql.setOnTouchListener touch@{ v, event ->
if (event.action != MotionEvent.ACTION_UP) return@touch false
val drawableEnd = (v as TextView).compoundDrawables[2] ?: return@touch false
val drawableLeft: Int
val drawableRight: Int

if (v.layoutDirection == LayoutDirection.LTR) {
drawableLeft = v.right - v.paddingEnd - drawableEnd.bounds.width()
drawableRight = v.right
} else {
drawableLeft = 0
drawableRight = v.paddingEnd + drawableEnd.bounds.width()
}

if (event.x >= drawableLeft && event.x <= drawableRight) {
SqlLogPopupWindow(this@DbManageFragment)
.setOnItemSelectedListener { popup, sqlLog ->
etSql.setText(sqlLog.sql)
etSql.setSelection(sqlLog.sql.length)
popup.dismiss()
}
.show(v)
return@touch true
}
return@touch false
}
}

override fun initData() {
Expand Down
88 changes: 88 additions & 0 deletions app/src/main/java/me/kbai/zhenxunui/ui/db/SqlLogPopupWindow.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package me.kbai.zhenxunui.ui.db

import android.view.Gravity
import android.view.View
import android.view.ViewGroup.LayoutParams
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.ArrayAdapter
import android.widget.PopupWindow
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import me.kbai.zhenxunui.R
import me.kbai.zhenxunui.databinding.PopupSqlLogBinding
import me.kbai.zhenxunui.model.SqlLog
import me.kbai.zhenxunui.viewmodel.SqlLogViewModel


class SqlLogPopupWindow(host: Fragment) : PopupWindow(
View.inflate(host.requireContext(), R.layout.popup_sql_log, null)
) {
private val mBinding = PopupSqlLogBinding.bind(contentView)
private val mViewModel by host.viewModels<SqlLogViewModel>()

private val mObserver: Observer<List<SqlLog>>

private val mWindowManager = host.requireActivity().windowManager

private var mOnItemSelectedListener: ((SqlLogPopupWindow, SqlLog) -> Unit)? = null

init {
isFocusable = true
isOutsideTouchable = true
animationStyle = R.style.PopupAnim

mObserver = Observer { list ->
mBinding.lvSql.apply {
adapter = ArrayAdapter(
mBinding.root.context, R.layout.item_sql_log, 0, list.map { it.sql }
)
setOnItemClickListener { _, _, position, _ ->
mOnItemSelectedListener?.invoke(this@SqlLogPopupWindow, list[position])
}
}
mBinding.pbWaiting.isVisible = false
}
mViewModel.logs.observeForever(mObserver)
}

fun setOnItemSelectedListener(listener: (popup: SqlLogPopupWindow, sqlLog: SqlLog) -> Unit): SqlLogPopupWindow {
mOnItemSelectedListener = listener
return this
}

fun show(anchor: View) {
anchor.context.getSystemService(InputMethodManager::class.java)
.hideSoftInputFromWindow(anchor.windowToken, 0)

width = anchor.width
height = LayoutParams.WRAP_CONTENT
showAsDropDown(anchor, 0, 0, Gravity.BOTTOM)

val container: View = contentView.parent.let {
if (it is View) it else contentView
}
val params = (container.layoutParams as WindowManager.LayoutParams).apply {
flags = flags or WindowManager.LayoutParams.FLAG_DIM_BEHIND
dimAmount = 0.1f
}
mWindowManager.updateViewLayout(container, params)
}

override fun dismiss() {
mViewModel.logs.removeObserver(mObserver)

val container: View = contentView.parent.let {
if (it is View) it else contentView
}
val params = (container.layoutParams as WindowManager.LayoutParams).apply {
flags = flags and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()
dimAmount = 0f
}
mWindowManager.updateViewLayout(container, params)

super.dismiss()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ class ConversationFragment : BaseFragment<FragmentConversationBinding>() {
btnSend.isEnabled = !it.isNullOrEmpty()
}

btnSend.setOnDebounceClickListener {
btnSend.setOnDebounceClickListener { btn ->
val message = etText.text?.toString()
if (message.isNullOrEmpty()) {
return@setOnDebounceClickListener
}
etText.setText("")

mViewModel.sendMessage(mUserId, mGroupId, message)
.launchAndApiCollectIn(this@ConversationFragment) {
.launchAndApiCollectIn(this@ConversationFragment, btn) {
if (it.success()) {
mMessageAdapter.addData(
mViewModel.insertSentMessage(mGroupId, mUserId, message)
Expand All @@ -66,11 +66,6 @@ class ConversationFragment : BaseFragment<FragmentConversationBinding>() {
}
}

override fun onStart() {
super.onStart()
viewBinding.btnSend.isEnabled = true
}

override fun initData() {
mGroupId = arguments?.getString(ARGS_GROUP_ID)
mUserId = arguments?.getString(ARGS_USER_ID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class PluginTypeViewModel : ViewModel() {

fun modifyPluginData(position: Int, data: PluginInfo, notify: Boolean = true) {
val list = _plugins.value
list[position] = data
//后台接口 getPluginDetail version 错误, 固定为 0
list[position] = data.copy(version = list[position].version)
if (notify) _plugins.value = list
}
}
30 changes: 30 additions & 0 deletions app/src/main/java/me/kbai/zhenxunui/viewmodel/SqlLogViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package me.kbai.zhenxunui.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import me.kbai.zhenxunui.extends.apiCollect
import me.kbai.zhenxunui.model.SqlLog
import me.kbai.zhenxunui.repository.ApiRepository
import me.kbai.zhenxunui.tool.GlobalToast

class SqlLogViewModel : ViewModel() {
private val _logs: MutableLiveData<List<SqlLog>> = MutableLiveData()
val logs: LiveData<List<SqlLog>> = _logs

init {
requestSqlLog()
}

fun requestSqlLog() = viewModelScope.launch {
ApiRepository.getSqlLog().apiCollect {
if (it.success() && it.data != null) {
_logs.value = it.data.data
} else {
GlobalToast.showToast(it.message)
}
}
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/anim/anim_top_enter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromXScale="1.0"
android:fromYScale="0.0"
android:pivotX="50"
android:pivotY="0"
android:toXScale="1.0"
android:toYScale="1.0" />
9 changes: 9 additions & 0 deletions app/src/main/res/anim/anim_top_exit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50"
android:pivotY="0"
android:toXScale="1.0"
android:toYScale="0.0" />
7 changes: 7 additions & 0 deletions app/src/main/res/drawable/bg_list_item_round_bottom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/dn_white_gray" />
<corners
android:bottomLeftRadius="@dimen/list_item_round"
android:bottomRightRadius="@dimen/list_item_round" />
</shape>
1 change: 1 addition & 0 deletions app/src/main/res/layout/fragment_db_manage.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
android:id="@+id/et_sql"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawableEnd="@drawable/ic_arrow_drop_down_16"
android:inputType="text"
android:padding="0dp"
android:textSize="@dimen/et_text_size"
Expand Down
Loading

0 comments on commit 3599c9d

Please sign in to comment.