@@ -154,6 +154,7 @@ class ActionPage : AppCompatActivity() {
154154 private val ACTION_FILE_PATH_CHOOSER_INNER = 65300
155155
156156 private var menuOptions: ArrayList <PageMenuOption >? = null
157+ private var menuCheckboxRefreshing = false
157158
158159 override fun onCreateOptionsMenu (menu : Menu ? ): Boolean {
159160 val config = currentPageConfig ? : return false
@@ -165,12 +166,52 @@ class ActionPage : AppCompatActivity() {
165166 if (option.isFab) {
166167 addFab(option)
167168 } else {
168- menu?.add(- 1 , index, index, option.title)
169+ val menuItem = menu?.add(- 1 , index, index, option.title)
170+ if (option.type == " checkbox" ) {
171+ menuItem?.isCheckable = true
172+ menuItem?.isChecked = option.checked
173+ }
169174 }
170175 }
171176 return true
172177 }
173178
179+ // Được Android gọi MỖI LẦN menu chuẩn bị hiển thị (khác onCreateOptionsMenu chỉ chạy 1 lần),
180+ // nên đây mới là chỗ đúng để refresh trạng thái tích mỗi khi người dùng mở menu.
181+ override fun onPrepareOptionsMenu (menu : Menu ): Boolean {
182+ refreshCheckboxMenuStates()
183+ return super .onPrepareOptionsMenu(menu)
184+ }
185+
186+ // Chạy các lệnh checked-sh ở nền (IO thread) để không làm treo UI mỗi lần mở menu.
187+ // Chỉ rebuild lại menu (invalidateOptionsMenu) khi có ít nhất 1 trạng thái thực sự thay đổi,
188+ // để tránh vòng lặp refresh vô tận (onPrepareOptionsMenu sẽ được gọi lại sau khi rebuild).
189+ private fun refreshCheckboxMenuStates () {
190+ val config = currentPageConfig ? : return
191+ val checkboxOptions = menuOptions?.filter { it.type == " checkbox" && it.checkedSh.isNotEmpty() }
192+ if (checkboxOptions.isNullOrEmpty() || menuCheckboxRefreshing) return
193+ menuCheckboxRefreshing = true
194+
195+ lifecycleScope.launch(Dispatchers .IO ) {
196+ val results = checkboxOptions.map { option ->
197+ option to ScriptEnvironmen .executeResultRoot(this @ActionPage, option.checkedSh, config)?.trim()
198+ }
199+
200+ withContext(Dispatchers .Main ) {
201+ menuCheckboxRefreshing = false
202+ var changed = false
203+ results.forEach { (option, result) ->
204+ val newChecked = result == " 1" || result?.lowercase() == " true"
205+ if (option.checked != newChecked) changed = true
206+ option.checked = newChecked
207+ }
208+ if (changed && ! isFinishing) {
209+ invalidateOptionsMenu()
210+ }
211+ }
212+ }
213+ }
214+
174215 private fun addFab (menuOption : PageMenuOption ) {
175216 binding.actionPageFab.apply {
176217 visibility = View .VISIBLE
0 commit comments