@@ -11,179 +11,169 @@ import com.omarea.common.ui.AdapterAppChooser
1111import com.omarea.common.ui.DialogAppChooser
1212import com.omarea.krscript.R
1313import com.omarea.krscript.model.ActionParamInfo
14- import java.text.Collator
1514import java.util.Locale
16- import java.util.HashMap
17- import java.util.HashSet
18- import java.util.ArrayList
19-
20- class ParamsAppChooserRender (
21- private var actionParamInfo : ActionParamInfo ,
22- private var context : FragmentActivity
23- ) : DialogAppChooser.Callback {
24-
25- companion object {
26- // Cache danh sách app để tránh load lại nhiều lần
27- private var cachedApps: List <AdapterAppChooser .AppInfo >? = null
28- private var cachedAppsWithMissing: List <AdapterAppChooser .AppInfo >? = null
29- }
15+ import java.text.Collator
3016
17+ class ParamsAppChooserRender (private var actionParamInfo : ActionParamInfo , private var context : FragmentActivity ) : DialogAppChooser.Callback {
18+ // Sử dụng Configuration để xác định chế độ sáng/tối
3119 private val uiMode = context.resources.configuration.uiMode
32- private val darkMode =
33- (uiMode and Configuration .UI_MODE_NIGHT_MASK ) == Configuration .UI_MODE_NIGHT_YES
20+ private var darkMode: Boolean = (uiMode and Configuration .UI_MODE_NIGHT_MASK ) == Configuration .UI_MODE_NIGHT_YES
3421
3522 private lateinit var valueView: TextView
3623 private lateinit var nameView: TextView
3724 private lateinit var packages: ArrayList <AdapterAppChooser .AppInfo >
3825
3926 fun render (): View {
40- val layout = LayoutInflater .from(context)
41- .inflate(R .layout.kr_param_app, null )
42-
27+ val layout = LayoutInflater .from(context).inflate(R .layout.kr_param_app, null )
4328 valueView = layout.findViewById(R .id.kr_param_app_package)
4429 nameView = layout.findViewById(R .id.kr_param_app_name)
4530
4631 setTextView()
4732
48- layout.findViewById<View >(R .id.kr_param_app_btn)
49- .setOnClickListener { openAppChooser() }
50-
51- nameView.setOnClickListener { openAppChooser() }
33+ layout.findViewById<View >(R .id.kr_param_app_btn).setOnClickListener {
34+ openAppChooser()
35+ }
36+ nameView.setOnClickListener {
37+ openAppChooser()
38+ }
5239
5340 valueView.tag = actionParamInfo.name
41+
5442 return layout
5543 }
5644
5745 private fun openAppChooser () {
5846 setSelectStatus()
59- DialogAppChooser (
60- darkMode,
61- packages,
62- actionParamInfo.multiple,
63- this
64- ).show(context.supportFragmentManager, " app-chooser" )
47+
48+ // Gọi DialogAppChooser với chế độ tối/sáng
49+ DialogAppChooser (darkMode, packages, actionParamInfo.multiple, this ).show(context.supportFragmentManager, " app-chooser" )
6550 }
6651
67- /* *
68- * Load & cache danh sách app (tối ưu PM + tránh O(n²))
69- */
70- private fun loadPackages (includeMissing : Boolean ): List <AdapterAppChooser .AppInfo > {
71- if (! includeMissing && cachedApps != null ) return cachedApps!!
72- if (includeMissing && cachedAppsWithMissing != null ) return cachedAppsWithMissing!!
73-
74- val pm = context.packageManager
75- val filterSet = actionParamInfo.optionsFromShell
76- ?.mapTo(HashSet ()) { it.value }
77-
78- val appMap = HashMap <String , AdapterAppChooser .AppInfo >(128 )
79-
80- pm.getInstalledApplications(PackageManager .MATCH_ALL ).forEach { app ->
81- val pkg = app.packageName
82- if (filterSet == null || filterSet.contains(pkg)) {
83- appMap[pkg] = AdapterAppChooser .AppInfo ().apply {
84- packageName = pkg
85- appName = app.loadLabel(pm).toString()
86- }
52+ private fun loadPackages (includeMissing : Boolean = false): ArrayList <AdapterAppChooser .AppInfo > {
53+ val pm = context.packageManager
54+
55+ val filterSet = actionParamInfo.optionsFromShell
56+ ?.map { it.value }
57+ ?.toHashSet()
58+
59+ val result = HashMap <String , AdapterAppChooser .AppInfo >(128 )
60+
61+ pm.getInstalledApplications(PackageManager .MATCH_ALL ).forEach { app ->
62+ val pkg = app.packageName
63+ if (filterSet == null || filterSet.contains(pkg)) {
64+ result[pkg] = AdapterAppChooser .AppInfo ().apply {
65+ packageName = pkg
66+ appName = app.loadLabel(pm)?.toString() ? : pkg
8767 }
8868 }
69+ }
8970
90- // include missing packages
91- if (includeMissing && actionParamInfo.optionsFromShell != null ) {
92- for (item in actionParamInfo.optionsFromShell!! ) {
93- val pkg = item.value ? : continue
94- if (! appMap.containsKey(pkg)) {
95- appMap[pkg] = AdapterAppChooser .AppInfo ().apply {
96- packageName = pkg
97- appName = item.title ? : " "
98- }
71+ // thêm app bị thiếu
72+ if (includeMissing && actionParamInfo.optionsFromShell != null ) {
73+ for (item in actionParamInfo.optionsFromShell!! ) {
74+ if (! result.containsKey(item.value)) {
75+ result[item.value] = AdapterAppChooser .AppInfo ().apply {
76+ packageName = item.value
77+ appName = item.title ? : item.value
9978 }
10079 }
10180 }
81+ }
10282
103- val collator = Collator .getInstance(Locale .getDefault())
104- val result = appMap.values.sortedWith { a, b ->
105- collator.compare(a.appName ? : " " , b.appName ? : " " )
106- }
83+ return ArrayList (result.values)
84+ }
10785
108- if (includeMissing) {
109- cachedAppsWithMissing = result
86+ private fun setSelectStatus () {
87+ packages.forEach {
88+ it.selected = false
89+ }
90+ val currentValue = valueView.text
91+ if (actionParamInfo.multiple) {
92+ currentValue.split(actionParamInfo.separator).run {
93+ this .forEach {
94+ val value = it
95+ val app = packages.find { it.packageName == value }
96+ if (app != null ) {
97+ app.selected = true
98+ }
99+ }
100+ }
110101 } else {
111- cachedApps = result
102+ val current = packages.find { it.packageName == currentValue }
103+ val currentIndex = if (current != null ) packages.indexOf(current) else - 1
104+ if (currentIndex > - 1 ) {
105+ packages[currentIndex].selected = true
106+ }
112107 }
113- return result
114108 }
115109
116- /* *
117- * Đặt trạng thái selected (O(n))
118- */
119- private fun setSelectStatus () {
120- val map = packages
121- .filter { it.packageName != null }
122- .associateBy { it.packageName!! }
123- packages.forEach { it.selected = false }
110+ // 设置界面显示和元素赋值
111+ private fun setTextView () {
112+ packages = loadPackages(actionParamInfo.type == " packages" )
124113
125- if (actionParamInfo.multiple) {
126- valueView.text
127- .split(actionParamInfo.separator)
128- .forEach { map[it]?.selected = true }
129- } else {
130- map[valueView.text]?.selected = true
131- }
114+ // sort theo locale
115+ val collator = Collator .getInstance(Locale .getDefault())
116+ packages.sortWith { a, b ->
117+ collator.compare(a.appName ? : " " , b.appName ? : " " )
132118 }
133119
134- /* *
135- * Gán dữ liệu hiển thị ban đầu
136- */
137- private fun setTextView () {
138- packages = ArrayList (loadPackages(actionParamInfo.type == " packages" ))
120+ // map nhanh theo packageName
121+ val packageMap = packages
122+ .filter { it.packageName != null }
123+ .associateBy { it.packageName!! }
139124
140- if (actionParamInfo.multiple) {
141- ActionParamsLayoutRender .getParamValues(actionParamInfo)
142- ?.forEach { value ->
143- packages.firstOrNull { it.packageName == value }?.selected = true
144- }
145- onConfirm(packages.filter { it.selected })
146- } else {
147- val validOptions = ArrayList <SelectItem >(packages.size)
148- packages.forEach {
149- validOptions.add(
150- SelectItem ().apply {
151- title = it.appName ? : " "
152- value = it.packageName ? : " "
153- }
154- )
125+ if (actionParamInfo.multiple) {
126+ ActionParamsLayoutRender .getParamValues(actionParamInfo)
127+ ?.forEach { value ->
128+ packageMap[value]?.selected = true
155129 }
156130
157- val currentIndex =
158- ActionParamsLayoutRender .getParamOptionsCurrentIndex(
159- actionParamInfo,
160- validOptions
161- )
131+ // giữ hành vi cũ: hiển thị ngay
132+ onConfirm(packages.filter { it.selected })
162133
163- if (currentIndex >= 0 ) {
164- val item = packages[currentIndex]
165- valueView.text = item.packageName ? : " "
166- nameView.text = item.appName ? : " "
167- } else {
168- valueView.text = " "
169- nameView.text = " "
170- }
134+ } else {
135+ val validOptions = ArrayList <SelectItem >(packages.size)
136+ packages.forEach {
137+ validOptions.add(
138+ SelectItem ().apply {
139+ title = it.appName ? : " "
140+ value = it.packageName ? : " "
141+ }
142+ )
143+ }
144+
145+ val currentIndex =
146+ ActionParamsLayoutRender .getParamOptionsCurrentIndex(
147+ actionParamInfo,
148+ validOptions
149+ )
150+
151+ if (currentIndex >= 0 ) {
152+ val item = packages[currentIndex]
153+ valueView.text = item.packageName.orEmpty()
154+ nameView.text = item.appName.orEmpty()
155+ } else {
156+ valueView.text = " "
157+ nameView.text = " "
171158 }
172159 }
160+ }
173161
174- /* *
175- * Callback từ DialogAppChooser
176- */
177162 override fun onConfirm (apps : List <AdapterAppChooser .AppInfo >) {
178163 if (actionParamInfo.multiple) {
179- valueView.text =
180- apps.joinToString(actionParamInfo.separator ) { it.packageName ? : " " }
181- nameView .text =
182- apps.joinToString( " , " ) { it.appName ? : " " }
164+ val values = apps.joinToString(actionParamInfo.separator) { it.packageName }
165+ val labels = apps.joinToString(" , " ) { it.appName }
166+ valueView .text = values
167+ nameView.text = labels
183168 } else {
184169 val item = apps.firstOrNull()
185- valueView.text = item?.packageName.orEmpty()
186- nameView.text = item?.appName.orEmpty()
170+ if (item == null ) {
171+ valueView.text = " "
172+ nameView.text = " "
173+ } else {
174+ valueView.text = item.packageName
175+ nameView.text = item.appName
176+ }
187177 }
188178 }
189179}
0 commit comments