mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Add worker info screen (#8774)
Mainly for debug purpose, might help with support.
This commit is contained in:
		@@ -118,6 +118,7 @@ object SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
    private fun getBackgroundActivityGroup(): Preference.PreferenceGroup {
 | 
			
		||||
        val context = LocalContext.current
 | 
			
		||||
        val uriHandler = LocalUriHandler.current
 | 
			
		||||
        val navigator = LocalNavigator.currentOrThrow
 | 
			
		||||
 | 
			
		||||
        return Preference.PreferenceGroup(
 | 
			
		||||
            title = stringResource(R.string.label_background_activity),
 | 
			
		||||
@@ -149,6 +150,10 @@ object SettingsAdvancedScreen : SearchableSettings {
 | 
			
		||||
                    subtitle = stringResource(R.string.about_dont_kill_my_app),
 | 
			
		||||
                    onClick = { uriHandler.openUri("https://dontkillmyapp.com/") },
 | 
			
		||||
                ),
 | 
			
		||||
                Preference.PreferenceItem.TextPreference(
 | 
			
		||||
                    title = stringResource(R.string.pref_worker_info),
 | 
			
		||||
                    onClick = { navigator.push(WorkerInfoScreen) },
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,161 @@
 | 
			
		||||
package eu.kanade.presentation.more.settings.screen
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import androidx.compose.foundation.horizontalScroll
 | 
			
		||||
import androidx.compose.foundation.layout.PaddingValues
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.rememberScrollState
 | 
			
		||||
import androidx.compose.material.icons.Icons
 | 
			
		||||
import androidx.compose.material.icons.filled.ArrowBack
 | 
			
		||||
import androidx.compose.material.icons.filled.ContentCopy
 | 
			
		||||
import androidx.compose.material3.Icon
 | 
			
		||||
import androidx.compose.material3.IconButton
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.SnackbarHost
 | 
			
		||||
import androidx.compose.material3.SnackbarHostState
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.material3.TopAppBar
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.collectAsState
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.runtime.rememberCoroutineScope
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.platform.LocalClipboardManager
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.text.AnnotatedString
 | 
			
		||||
import androidx.compose.ui.text.font.FontFamily
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import androidx.lifecycle.asFlow
 | 
			
		||||
import androidx.work.WorkInfo
 | 
			
		||||
import androidx.work.WorkManager
 | 
			
		||||
import androidx.work.WorkQuery
 | 
			
		||||
import cafe.adriel.voyager.core.model.ScreenModel
 | 
			
		||||
import cafe.adriel.voyager.core.model.coroutineScope
 | 
			
		||||
import cafe.adriel.voyager.core.model.rememberScreenModel
 | 
			
		||||
import cafe.adriel.voyager.core.screen.Screen
 | 
			
		||||
import cafe.adriel.voyager.navigator.LocalNavigator
 | 
			
		||||
import cafe.adriel.voyager.navigator.currentOrThrow
 | 
			
		||||
import eu.kanade.presentation.components.LazyColumn
 | 
			
		||||
import eu.kanade.presentation.components.Scaffold
 | 
			
		||||
import eu.kanade.presentation.util.plus
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import kotlinx.coroutines.flow.SharingStarted
 | 
			
		||||
import kotlinx.coroutines.flow.map
 | 
			
		||||
import kotlinx.coroutines.flow.stateIn
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
 | 
			
		||||
object WorkerInfoScreen : Screen {
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    override fun Content() {
 | 
			
		||||
        val context = LocalContext.current
 | 
			
		||||
        val navigator = LocalNavigator.currentOrThrow
 | 
			
		||||
        val clipboardManager = LocalClipboardManager.current
 | 
			
		||||
 | 
			
		||||
        val screenModel = rememberScreenModel { Model(context) }
 | 
			
		||||
        val enqueued by screenModel.enqueued.collectAsState()
 | 
			
		||||
        val finished by screenModel.finished.collectAsState()
 | 
			
		||||
        val running by screenModel.running.collectAsState()
 | 
			
		||||
 | 
			
		||||
        val snackbarHostState = remember { SnackbarHostState() }
 | 
			
		||||
        val scope = rememberCoroutineScope()
 | 
			
		||||
 | 
			
		||||
        Scaffold(
 | 
			
		||||
            topBar = {
 | 
			
		||||
                TopAppBar(
 | 
			
		||||
                    title = { Text(text = stringResource(R.string.pref_worker_info)) },
 | 
			
		||||
                    navigationIcon = {
 | 
			
		||||
                        IconButton(onClick = navigator::pop) {
 | 
			
		||||
                            Icon(imageVector = Icons.Default.ArrowBack, contentDescription = null)
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    actions = {
 | 
			
		||||
                        val copiedString = stringResource(R.string.copied_to_clipboard_plain)
 | 
			
		||||
                        IconButton(
 | 
			
		||||
                            onClick = {
 | 
			
		||||
                                clipboardManager.setText(AnnotatedString(enqueued + finished + running))
 | 
			
		||||
                                scope.launch { snackbarHostState.showSnackbar(copiedString) }
 | 
			
		||||
                            },
 | 
			
		||||
                        ) {
 | 
			
		||||
                            Icon(imageVector = Icons.Default.ContentCopy, contentDescription = null)
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    scrollBehavior = it,
 | 
			
		||||
                )
 | 
			
		||||
            },
 | 
			
		||||
            snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
 | 
			
		||||
        ) { contentPadding ->
 | 
			
		||||
            LazyColumn(
 | 
			
		||||
                contentPadding = contentPadding + PaddingValues(horizontal = 16.dp),
 | 
			
		||||
                modifier = Modifier.horizontalScroll(rememberScrollState()),
 | 
			
		||||
            ) {
 | 
			
		||||
                item { SectionTitle(title = "Enqueued") }
 | 
			
		||||
                item { SectionText(text = enqueued) }
 | 
			
		||||
 | 
			
		||||
                item { SectionTitle(title = "Finished") }
 | 
			
		||||
                item { SectionText(text = finished) }
 | 
			
		||||
 | 
			
		||||
                item { SectionTitle(title = "Running") }
 | 
			
		||||
                item { SectionText(text = running) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    private fun SectionTitle(title: String) {
 | 
			
		||||
        Text(
 | 
			
		||||
            text = title,
 | 
			
		||||
            style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
            modifier = Modifier.padding(vertical = 8.dp),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Composable
 | 
			
		||||
    private fun SectionText(text: String) {
 | 
			
		||||
        Text(
 | 
			
		||||
            text = text,
 | 
			
		||||
            softWrap = false,
 | 
			
		||||
            fontFamily = FontFamily.Monospace,
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private class Model(context: Context) : ScreenModel {
 | 
			
		||||
        private val workManager = WorkManager.getInstance(context)
 | 
			
		||||
 | 
			
		||||
        val finished = workManager
 | 
			
		||||
            .getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED))
 | 
			
		||||
            .asFlow()
 | 
			
		||||
            .map(::constructString)
 | 
			
		||||
            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), "")
 | 
			
		||||
 | 
			
		||||
        val running = workManager
 | 
			
		||||
            .getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.RUNNING))
 | 
			
		||||
            .asFlow()
 | 
			
		||||
            .map(::constructString)
 | 
			
		||||
            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), "")
 | 
			
		||||
 | 
			
		||||
        val enqueued = workManager
 | 
			
		||||
            .getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.ENQUEUED))
 | 
			
		||||
            .asFlow()
 | 
			
		||||
            .map(::constructString)
 | 
			
		||||
            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), "")
 | 
			
		||||
 | 
			
		||||
        private fun constructString(list: List<WorkInfo>) = buildString {
 | 
			
		||||
            if (list.isEmpty()) {
 | 
			
		||||
                appendLine("-")
 | 
			
		||||
            } else {
 | 
			
		||||
                list.forEach { workInfo ->
 | 
			
		||||
                    appendLine("Id: ${workInfo.id}")
 | 
			
		||||
                    appendLine("Tags:")
 | 
			
		||||
                    workInfo.tags.forEach {
 | 
			
		||||
                        appendLine(" - $it")
 | 
			
		||||
                    }
 | 
			
		||||
                    appendLine("State: ${workInfo.state}")
 | 
			
		||||
                    appendLine()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user