Skip to content

Commit

Permalink
feat:全局搜索功能开发中
Browse files Browse the repository at this point in the history
  • Loading branch information
Yricky committed Aug 30, 2024
1 parent f2c7b1b commit 6f1e520
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 26 deletions.
170 changes: 170 additions & 0 deletions abcdecoder/src/jvmMain/kotlin/me/yricky/abcde/content/AbcUniSearch.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package me.yricky.abcde.content

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import me.yricky.abcde.HapSession
import me.yricky.abcde.page.AbcView
import me.yricky.abcde.ui.LazyColumnWithScrollBar
import me.yricky.abcde.ui.codeStyle
import me.yricky.abcde.ui.defineStr
import me.yricky.oh.abcd.AbcBuf
import me.yricky.oh.abcd.cfm.AbcClass
import me.yricky.oh.abcd.cfm.AbcMethod
import me.yricky.oh.abcd.cfm.ClassItem
import me.yricky.oh.abcd.isa.calledStrings

class AbcUniSearchState(
val abc:AbcBuf,
val searchScope:CoroutineScope
){
var filterText by mutableStateOf("")


class SearchSession(
val job:Job,
val filterText:String,
val searchTargets:Map<SearchTarget,SnapshotStateList<SearchResult>>,
val progress:State<Float>,
val finished:State<Boolean>
){
}

fun startSearch(
target: Set<SearchTarget>
):SearchSession{
val progress = mutableFloatStateOf(0f)
val targets = target.associateWith { mutableStateListOf<SearchResult>() }
val finished = mutableStateOf(false)
val job = searchScope.launch(Dispatchers.Default) {
abc.classes.values.forEachIndexed { i,c ->
targets.entries.forEach {
it.value.addAll(it.key.find(filterText,c))
}
progress.value = i / abc.classes.size.toFloat()
}
finished.value = true
}
return SearchSession(job,filterText,targets,progress,finished)
}

var session by mutableStateOf<AbcUniSearchState.SearchSession?>(null)

sealed class SearchTarget{
abstract fun find(filterText:String,classItem: ClassItem):List<SearchResult>
}
object ClassPath:SearchTarget(){
override fun find(filterText:String,classItem: ClassItem): List<SearchResult> {
return if(classItem.name.contains(filterText)){
listOf(ClassResult(classItem))
} else {
emptyList()
}
}

}
object MethodName:SearchTarget(){
override fun find(filterText: String, classItem: ClassItem): List<SearchResult> {
return when(classItem){
is AbcClass -> classItem.methods.filter { it.name.contains(filterText) }.map { MethodResult(classItem,it) }
else -> emptyList()
}
}

}
object ASM:SearchTarget(){
override fun find(filterText: String, classItem: ClassItem): List<SearchResult> {
return when(classItem){
is AbcClass -> classItem.methods.filter {
it.codeItem?.asm?.list?.any {
it.calledStrings.any { it.contains(filterText) }
} ?: false
}.map { CodeResult(classItem,it) }
else -> emptyList()
}
}

}

sealed class SearchResult()
class ClassResult(val classItem: ClassItem):SearchResult()
class MethodResult(val classItem: AbcClass,val method: AbcMethod):SearchResult()
class CodeResult(val classItem: AbcClass,val method: AbcMethod):SearchResult()
}

@Composable
fun AbcUniSearchStateView(
hapSession: HapSession,
abc:AbcView,
state:AbcUniSearchState
){
Column {
Row(
Modifier.fillMaxWidth().height(40.dp)
.border(1.dp,MaterialTheme.colorScheme.surfaceVariant),
verticalAlignment = Alignment.CenterVertically
) {
BasicTextField(
state.filterText,{state.filterText = it},
textStyle = codeStyle,
singleLine = true,
maxLines = 1,
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary)
)
Button({
state.session?.job?.cancel()
state.session = state.startSearch(setOf(AbcUniSearchState.MethodName,AbcUniSearchState.ASM))
}){
Text("查询")
}
}

state.session?.let {
AnimatedVisibility(!it.finished.value) {
LinearProgressIndicator(progress = { it.progress.value }, modifier = Modifier.fillMaxWidth())
}
LazyColumnWithScrollBar {
it.searchTargets.forEach { t, u ->
items(u){
when(it){
is AbcUniSearchState.ClassResult -> {
Text("class:${it.classItem.name}", modifier = Modifier.clickable {
if(it.classItem is AbcClass){
hapSession.openClass(abc.hap,it.classItem)
}
})
}
is AbcUniSearchState.MethodResult -> {
Text("method:${it.method.defineStr(true)}", modifier = Modifier.clickable {
hapSession.openCode(abc.hap,it.method)
})
}
is AbcUniSearchState.CodeResult -> {
Text("code:${it.method.defineStr(true)}", modifier = Modifier.clickable {
hapSession.openCode(abc.hap,it.method)
})
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package me.yricky.abcde.content

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import me.yricky.abcde.desktop.DesktopUtils
import me.yricky.abcde.ui.ABCDEWindow
import me.yricky.abcde.ui.Icons
import me.yricky.abcde.ui.LocalAppConfig
import me.yricky.abcde.ui.isDarkTheme
import me.yricky.abcde.ui.*

@Composable
fun SettingsPanel(show:Boolean,onDismiss:()->Unit){
Expand All @@ -26,12 +22,16 @@ fun SettingsPanel(show:Boolean,onDismiss:()->Unit){
icon = Icons.editorConfig(),
title = "设置"
){
Column(Modifier.fillMaxSize().padding(8.dp)) {
OutlinedCard() {
val cfg = LocalAppConfig.current
val cfg = LocalAppConfig.current
val scope = rememberCoroutineScope()
Column(Modifier.fillMaxSize().padding(horizontal = 8.dp)) {
ConfigGroup("外观",Modifier.padding(top=8.dp)) {
var newDensity by remember { mutableStateOf(cfg.density) }
val scope = rememberCoroutineScope()
Text("DPI缩放:${String.format("%.02f",newDensity)}", modifier = Modifier.padding(horizontal = 8.dp))
Text(
"DPI缩放:${String.format("%.02f",newDensity)}",
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(start = 8.dp, top = 8.dp)
)
Slider(
value = newDensity,
onValueChange = { newDensity = it },
Expand All @@ -42,20 +42,62 @@ fun SettingsPanel(show:Boolean,onDismiss:()->Unit){
}
}
},

valueRange = 0.5f .. 3f,
steps = 49
)
Text("颜色主题")
Icon(if(isDarkTheme()) Icons.darkTheme() else Icons.lightTheme(), null, Modifier.size(28.dp).clip(
CircleShape
).clickable {
scope.launch {
DesktopUtils.AppConfig.edit{
it.copy(darkTheme = it.darkTheme?.not() ?: false)

Row(
Modifier.height(40.dp).clickable {
scope.launch {
DesktopUtils.AppConfig.edit{
it.copy(darkTheme = it.darkTheme?.not() ?: false)
}
}
}
}.padding(4.dp))
}.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
"颜色主题",Modifier.weight(1f),
style = MaterialTheme.typography.titleMedium,
)
Icon(if(isDarkTheme()) Icons.darkTheme() else Icons.lightTheme(), null, Modifier.size(20.dp).clip(
CircleShape
))
}
}
ConfigGroup("进阶设置",Modifier.padding(top=8.dp)){
Row(
Modifier.height(40.dp).clickable {
scope.launch {
DesktopUtils.AppConfig.edit{
it.copy(futureFeature = it.futureFeature.not())
}
}
}.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
"启用开发中功能",Modifier.weight(1f),
style = MaterialTheme.typography.titleMedium,
)
Checkbox(cfg.futureFeature,{})
}
}
}
}
}

@Composable
fun ConfigGroup(
title:String,
modifier: Modifier = Modifier,
content:@Composable ColumnScope.()->Unit
){
Column(modifier) {
Text(title, style = MaterialTheme.typography.titleLarge, modifier = Modifier.padding(start = 8.dp))
OutlinedCard {
content()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ object DesktopUtils {
@SerialName("historyList")
val historyList:List<String> = emptyList(),
@SerialName("darkTheme")
val darkTheme:Boolean? = true
val darkTheme:Boolean? = true,
@SerialName("futureFeature")
val futureFeature:Boolean = false,
){
companion object{
suspend fun edit(action: (AppConfig) -> AppConfig){
Expand Down
16 changes: 14 additions & 2 deletions abcdecoder/src/jvmMain/kotlin/me/yricky/abcde/page/AbcView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import me.yricky.abcde.AppState
import me.yricky.abcde.HapSession
import me.yricky.abcde.content.AbcUniSearchState
import me.yricky.abcde.content.AbcUniSearchStateView
import me.yricky.abcde.ui.*
import me.yricky.abcde.util.TreeModel
import me.yricky.oh.abcd.AbcBuf
Expand All @@ -33,7 +36,8 @@ class AbcView(val abc: AbcBuf,override val hap:HapView? = null):AttachHapPage()
@Composable
override fun Page(modifier: Modifier, hapSession: HapSession, appState: AppState) {
val scope = rememberCoroutineScope()
VerticalTabAndContent(modifier, listOf(composeSelectContent{ _: Boolean ->
val appCfg = LocalAppConfig.current
VerticalTabAndContent(modifier, listOfNotNull(composeSelectContent{ _: Boolean ->
Image(Icons.clazz(), null, Modifier.fillMaxSize(), colorFilter = grayColorFilter)
} to composeContent{
Column(Modifier.fillMaxSize().padding(end = 4.dp)) {
Expand Down Expand Up @@ -110,10 +114,18 @@ class AbcView(val abc: AbcBuf,override val hap:HapView? = null):AttachHapPage()
scope.launch(Dispatchers.Default) { realCkSum = realCheckSum.value }
})
}
}
}, if(appCfg.futureFeature) {
composeSelectContent {
Image(Icons.search(), null, Modifier.fillMaxSize(), colorFilter = grayColorFilter)
} to composeContent {
AbcUniSearchStateView(hapSession, this, searchState)
}
} else null
))
}

val searchState = AbcUniSearchState(abc, CoroutineScope(Dispatchers.Default))

private val classMap get()= abc.classes
var filter by mutableStateOf("")
private set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.foundation.LocalScrollbarStyle
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.*
Expand Down Expand Up @@ -75,7 +76,7 @@ fun ABCDEWindow(
LaunchedEffect(null){
window.background = java.awt.Color(bgColor.value.toInt())
}
Box(Modifier.background(MaterialTheme.colorScheme.background)) {
Surface(color = bgColor) {
windowScope.content()
}
}
Expand Down

0 comments on commit 6f1e520

Please sign in to comment.