Clean up some build warnings (#2929)

* Replace deprecated rememberPlainTooltipPositionProvider

* Remove superfluous when branch

This when is marked as exhaustive.

* Replace deprecated LibrariesContainer call

AboutLibraries now wants us to produce the libraries ourselves.

* Replace deprecated ClipboardManager with Clipboard

Clipboard uses suspend functions, hence the coroutine scope addition.

* Use multi-dollar strs to simplify GraphQL queries

These have been available since Kotlin 2.1.

* Remove various redundant casts & conversions

- WebViewScreenContent: loadingState is in the LoadingState.Loading
  branch, no need to cast at all
- Bangumi: username is not modified, make val
- Kavita: token is already a String
- PagerViewerAdapter: insertPageLastPage is already null-checked
- PagerViewerAdapter: use reified filterIsInstance
- ReaderViewModel: chapter IDs are already Longs
- CloudflareInterceptor: webview is smart-cast to non-null here

* Replace deprecated MenuAnchorType

Literally just a typealias for ExposedDropdownMenuAnchorType anyway.

* OptimizeNonSkippingGroups is enabled by default

* Suppress shadowing warning

This is explicitly intentional according to the KDocs.

* Migrate Context Receivers to Context Parameters

Requires changing the compiler arg, but that is part of the migration:

https://blog.jetbrains.com/kotlin/2025/04/update-on-context-parameters

Apparently, the only visible change is that names are required now.
"_" can be used for anonymous context parameters.

* Fix expression bodies with explicit return

Naming conflict resolved by aliasing.

From 2.4/2.5 onward, these will only be allowed with explicit return
types, or have to be turned into a block body. I opted for the latter
since the function is reasonably dense already.

see: https://youtrack.jetbrains.com/issue/KTLC-288

* Suppress deprecation of non-AutoMirrored icons

We use these arrows for navigation in the Upcoming screen.
I strongly doubt the AutoMirrored versions would make sense for our
use-case.

* Explicitly opt-in to new annotation default rules

affects the following annotated value-parameters:
- Preference.SliderPreference.steps (`@IntRange`)
- ReaderViewModel.State.brightnessOverlayValue (`@IntRange`)
- ReadingMode.iconRes (`@DrawableRes`)
- MigrationListScreenModel.Dialog.Progress.progress (`@FloatRange`)

see: https://youtrack.jetbrains.com/issue/KT-73255
see: https://github.com/Kotlin/KEEP/blob/change-defaulting-rule/proposals/annotation-target-in-properties.md

Warning message was the following:

    This annotation is currently applied to the value parameter only, but in the future it will also be applied to field.
    - To opt in to applying to both value parameter and field, add '-Xannotation-default-target=param-property' to your compiler arguments.
    - To keep applying to the value parameter only, use the '@param:' annotation target.

(cherry picked from commit b543bc089a442c5e93b0fb6c83bc4037740b1eb5)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt
#	core/common/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt
#	core/common/src/main/kotlin/mihon/core/common/archive/ArchiveInputStream.kt
This commit is contained in:
MajorTanya
2026-02-05 06:29:21 +01:00
committed by Jobobby04
parent bb8698b2a6
commit 2034971cc0
22 changed files with 104 additions and 83 deletions
+1
View File
@@ -157,6 +157,7 @@ kotlin {
"-opt-in=kotlinx.coroutines.FlowPreview",
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi",
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
"-Xannotation-default-target=param-property",
)
}
}
@@ -21,8 +21,9 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.TooltipDefaults.rememberTooltipPositionProvider
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
@@ -195,7 +196,7 @@ fun AppBarActions(
actions.filterIsInstance<AppBar.Action>().map {
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
positionProvider = rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
tooltip = {
PlainTooltip {
Text(it.title)
@@ -220,7 +221,7 @@ fun AppBarActions(
val overflowActions = actions.filterIsInstance<AppBar.OverflowAction>()
if (overflowActions.isNotEmpty()) {
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
positionProvider = rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
tooltip = {
PlainTooltip {
Text(stringResource(MR.strings.action_menu_overflow_description))
@@ -349,7 +350,7 @@ fun SearchToolbar(
// Don't show search action
} else if (searchQuery == null) {
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
positionProvider = rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
tooltip = {
PlainTooltip {
Text(stringResource(MR.strings.action_search))
@@ -369,7 +370,7 @@ fun SearchToolbar(
}
} else if (searchQuery.isNotEmpty()) {
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
positionProvider = rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
tooltip = {
PlainTooltip {
Text(stringResource(MR.strings.action_reset))
@@ -245,7 +245,6 @@ object AboutScreen : Screen() {
is GetApplicationRelease.Result.OsTooOld -> {
context.toast(MR.strings.update_check_eol)
}
else -> {}
}
} catch (e: Exception) {
context.toast(e.message)
@@ -2,13 +2,16 @@ package eu.kanade.presentation.more.settings.screen.about
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries
import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
import com.mikepenz.aboutlibraries.ui.compose.util.htmlReadyLicenseContent
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.R
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource
@@ -27,7 +30,9 @@ class OpenSourceLicensesScreen : Screen() {
)
},
) { contentPadding ->
val libraries by produceLibraries(R.raw.aboutlibraries)
LibrariesContainer(
libraries = libraries,
modifier = Modifier
.fillMaxSize(),
contentPadding = contentPadding,
@@ -78,7 +78,7 @@ class DebugInfoScreen : Screen() {
val status by produceState(initialValue = "-") {
val result = ProfileVerifier.getCompilationStatusAsync().await().profileInstallResultCode
value = when (result) {
ProfileVerifier.CompilationStatus.RESULT_CODE_NO_PROFILE -> "No profile installed"
ProfileVerifier.CompilationStatus.RESULT_CODE_NO_PROFILE_INSTALLED -> "No profile installed"
ProfileVerifier.CompilationStatus.RESULT_CODE_COMPILED_WITH_PROFILE -> "Compiled"
ProfileVerifier.CompilationStatus.RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING ->
"Compiled non-matching"
@@ -1,5 +1,6 @@
package eu.kanade.presentation.track
import android.content.ClipData
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
@@ -47,6 +48,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -55,11 +57,11 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.Clipboard
import androidx.compose.ui.platform.LocalClipboard
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.platform.toClipEntry
import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.intl.Locale
@@ -73,6 +75,7 @@ import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.util.system.openInBrowser
import kotlinx.coroutines.launch
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
import tachiyomi.presentation.core.components.material.Scaffold
@@ -240,7 +243,7 @@ private fun SearchResultItem(
onClick: () -> Unit,
) {
val context = LocalContext.current
val clipboardManager: ClipboardManager = LocalClipboardManager.current
val clipboard: Clipboard = LocalClipboard.current
val focusManager = LocalFocusManager.current
val type = trackSearch.publishing_type.toLowerCase(Locale.current).capitalize(Locale.current)
val status = trackSearch.publishing_status.toLowerCase(Locale.current).capitalize(Locale.current)
@@ -248,6 +251,7 @@ private fun SearchResultItem(
val shape = RoundedCornerShape(16.dp)
val borderColor = if (selected) MaterialTheme.colorScheme.outline else Color.Transparent
var dropDownMenuExpanded by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
Box(
modifier = Modifier
.fillMaxWidth()
@@ -295,7 +299,13 @@ private fun SearchResultItem(
expanded = dropDownMenuExpanded,
onCollapseMenu = { dropDownMenuExpanded = false },
onCopyName = {
clipboardManager.setText(AnnotatedString(trackSearch.title))
scope.launch {
val clipEntry = ClipData.newPlainText(
trackSearch.title,
trackSearch.title,
).toClipEntry()
clipboard.setClipEntry(clipEntry)
}
},
onOpenInBrowser = {
val url = trackSearch.tracking_url
@@ -9,21 +9,21 @@ import tachiyomi.domain.source.model.SourceNotInstalledException
import tachiyomi.i18n.MR
import java.net.UnknownHostException
context(Context)
context(context: Context)
val Throwable.formattedMessage: String
get() {
when (this) {
is HttpException -> return stringResource(MR.strings.exception_http, code)
is HttpException -> return context.stringResource(MR.strings.exception_http, code)
is UnknownHostException -> {
return if (!isOnline()) {
stringResource(MR.strings.exception_offline)
return if (!context.isOnline()) {
context.stringResource(MR.strings.exception_offline)
} else {
stringResource(MR.strings.exception_unknown_host, message ?: "")
context.stringResource(MR.strings.exception_unknown_host, message ?: "")
}
}
is NoResultsException -> return stringResource(MR.strings.no_results_found)
is SourceNotInstalledException -> return stringResource(MR.strings.loader_not_implemented_error)
is NoResultsException -> return context.stringResource(MR.strings.no_results_found)
is SourceNotInstalledException -> return context.stringResource(MR.strings.loader_not_implemented_error)
}
return when (val className = this::class.simpleName) {
"Exception", "IOException" -> message ?: className
@@ -4,5 +4,7 @@ import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.ui.Modifier
// https://issuetracker.google.com/352584409
context(LazyItemScope)
fun Modifier.animateItemFastScroll() = this.animateItem(fadeInSpec = null, fadeOutSpec = null)
context(itemScope: LazyItemScope)
fun Modifier.animateItemFastScroll() = with(itemScope) {
this@animateItemFastScroll.animateItem(fadeInSpec = null, fadeOutSpec = null)
}
@@ -80,7 +80,7 @@ fun EhLoginWebViewScreen(
)
is LoadingState.Loading -> {
val animatedProgress by animateFloatAsState(
(loadingState as? LoadingState.Loading)?.progress ?: 1f,
loadingState.progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
label = "webview_loading",
)
@@ -273,7 +273,7 @@ fun WebViewScreenContent(
.align(Alignment.BottomCenter),
)
is LoadingState.Loading -> LinearProgressIndicator(
progress = { (loadingState as? LoadingState.Loading)?.progress ?: 1f },
progress = { loadingState.progress },
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter),
@@ -45,9 +45,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
suspend fun addLibManga(track: Track): Track {
return withIOContext {
val query = """
|mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus, ${'$'}private: Boolean) {
|SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status, private: ${'$'}private) {
val query = $$"""
|mutation AddManga($mangaId: Int, $progress: Int, $status: MediaListStatus, $private: Boolean) {
|SaveMediaListEntry (mediaId: $mangaId, progress: $progress, status: $status, private: $private) {
| id
| status
|}
@@ -82,14 +82,14 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
suspend fun updateLibManga(track: Track): Track {
return withIOContext {
val query = """
val query = $$"""
|mutation UpdateManga(
|${'$'}listId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus, ${'$'}private: Boolean,
|${'$'}score: Int, ${'$'}startedAt: FuzzyDateInput, ${'$'}completedAt: FuzzyDateInput
|$listId: Int, $progress: Int, $status: MediaListStatus, $private: Boolean,
|$score: Int, $startedAt: FuzzyDateInput, $completedAt: FuzzyDateInput
|) {
|SaveMediaListEntry(
|id: ${'$'}listId, progress: ${'$'}progress, status: ${'$'}status, private: ${'$'}private,
|scoreRaw: ${'$'}score, startedAt: ${'$'}startedAt, completedAt: ${'$'}completedAt
|id: $listId, progress: $progress, status: $status, private: $private,
|scoreRaw: $score, startedAt: $startedAt, completedAt: $completedAt
|) {
|id
|status
@@ -118,9 +118,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
suspend fun deleteLibManga(track: DomainTrack) {
withIOContext {
val query = """
|mutation DeleteManga(${'$'}listId: Int) {
|DeleteMediaListEntry(id: ${'$'}listId) {
val query = $$"""
|mutation DeleteManga($listId: Int) {
|DeleteMediaListEntry(id: $listId) {
|deleted
|}
|}
@@ -139,10 +139,10 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
suspend fun search(search: String): List<TrackSearch> {
return withIOContext {
val query = """
|query Search(${'$'}query: String) {
val query = $$"""
|query Search($query: String) {
|Page (perPage: 50) {
|media(search: ${'$'}query, type: MANGA, format_not_in: [NOVEL]) {
|media(search: $query, type: MANGA, format_not_in: [NOVEL]) {
|id
|staff {
|edges {
@@ -201,10 +201,10 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
suspend fun findLibManga(track: Track, userid: Int): Track? {
return withIOContext {
val query = """
|query (${'$'}id: Int!, ${'$'}manga_id: Int!) {
val query = $$"""
|query ($id: Int!, $manga_id: Int!) {
|Page {
|mediaList(userId: ${'$'}id, type: MANGA, mediaId: ${'$'}manga_id) {
|mediaList(userId: $id, type: MANGA, mediaId: $manga_id) {
|id
|status
|scoreRaw: score(format: POINT_100)
@@ -113,7 +113,7 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
// Users can set a 'username' (not nickname) once which effectively
// replaces the stringified ID in certain queries.
// If no username is set, the API returns the user ID as a strings
var username = api.getUsername()
val username = api.getUsername()
saveCredentials(username, oauth.accessToken)
} catch (_: Throwable) {
logout()
@@ -137,7 +137,7 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
}
authentication.apiUrl = prefApiUrl
authentication.jwtToken = token.toString()
authentication.jwtToken = token
}
authentications = oauth
}
@@ -37,14 +37,14 @@ class SuwayomiApi(private val trackId: Long) {
public fun sourcePreferences(): SharedPreferences = configurableSource.sourcePreferences()
suspend fun getTrackSearch(mangaId: Long): TrackSearch = withIOContext {
val query = """
|query GetManga(${'$'}mangaId: Int!) {
| manga(id: ${'$'}mangaId) {
val query = $$"""
|query GetManga($mangaId: Int!) {
| manga(id: $mangaId) {
| ...MangaFragment
| }
|}
|
|$MangaFragment
|$$MangaFragment
""".trimMargin()
val payload = buildJsonObject {
put("query", query)
@@ -87,9 +87,9 @@ class SuwayomiApi(private val trackId: Long) {
// TODO: Include a filter on the chapter number here
// Below, we only consider older chapters; since v2.1.1985 filtering works properly in the query
val chaptersQuery = """
|query GetMangaUnreadChapters(${'$'}mangaId: Int!) {
| chapters(condition: {mangaId: ${'$'}mangaId, isRead: false}) {
val chaptersQuery = $$"""
|query GetMangaUnreadChapters($mangaId: Int!) {
| chapters(condition: {mangaId: $mangaId, isRead: false}) {
| nodes {
| id
| chapterNumber
@@ -119,20 +119,20 @@ class SuwayomiApi(private val trackId: Long) {
}
val markQuery = if (deleteDownloadsOnServer) {
"""
|mutation MarkChaptersRead(${'$'}chapters: [Int!]!) {
| updateChapters(input: {ids: ${'$'}chapters, patch: {isRead: true}}) {
$$"""
|mutation MarkChaptersRead($chapters: [Int!]!) {
| updateChapters(input: {ids: $chapters, patch: {isRead: true}}) {
| __typename
| }
| deleteDownloadedChapters(input: {ids: ${'$'}chapters}) {
| deleteDownloadedChapters(input: {ids: $chapters}) {
| __typename
| }
|}
""".trimMargin()
} else {
"""
|mutation MarkChaptersRead(${'$'}chapters: [Int!]!) {
| updateChapters(input: {ids: ${'$'}chapters, patch: {isRead: true}}) {
$$"""
|mutation MarkChaptersRead($chapters: [Int!]!) {
| updateChapters(input: {ids: $chapters, patch: {isRead: true}}) {
| __typename
| }
|}
@@ -156,9 +156,9 @@ class SuwayomiApi(private val trackId: Long) {
.awaitSuccess()
}
val trackQuery = """
|mutation TrackManga(${'$'}mangaId: Int!) {
| trackProgress(input: {mangaId: ${'$'}mangaId}) {
val trackQuery = $$"""
|mutation TrackManga($mangaId: Int!) {
| trackProgress(input: {mangaId: $mangaId}) {
| __typename
| }
|}
@@ -655,7 +655,7 @@ class ReaderViewModel @JvmOverloads constructor(
* if setting is enabled and [currentChapter] is queued for download
*/
private fun cancelQueuedDownloads(currentChapter: ReaderChapter): Download? {
return downloadManager.getQueuedDownloadOrNull(currentChapter.chapter.id!!.toLong())?.also {
return downloadManager.getQueuedDownloadOrNull(currentChapter.chapter.id!!)?.also {
downloadManager.cancelQueuedDownloads(listOf(it))
}
}
@@ -848,7 +848,7 @@ class ReaderViewModel @JvmOverloads constructor(
viewModelScope.launchNonCancellable {
updateChapter.await(
ChapterUpdate(
id = chapter.id!!.toLong(),
id = chapter.id!!,
bookmark = bookmarked,
),
)
@@ -5,6 +5,7 @@ package androidx.preference
/**
* Returns package-private [EditTextPreference.getOnBindEditTextListener]
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
fun EditTextPreference.getOnBindEditTextListener(): EditTextPreference.OnBindEditTextListener? {
return onBindEditTextListener
}
@@ -54,9 +54,11 @@ fun CalenderHeader(
}
Row {
IconButton(onClick = onPreviousClick) {
@Suppress("DEPRECATION")
Icon(Icons.Default.KeyboardArrowLeft, stringResource(MR.strings.upcoming_calendar_prev))
}
IconButton(onClick = onNextClick) {
@Suppress("DEPRECATION")
Icon(Icons.Default.KeyboardArrowRight, stringResource(MR.strings.upcoming_calendar_next))
}
}
@@ -14,7 +14,6 @@ import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.the
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.File
@@ -42,7 +41,7 @@ internal fun Project.configureAndroid(commonExtension: CommonExtension<*, *, *,
compilerOptions {
jvmTarget.set(AndroidConfig.JvmTarget)
freeCompilerArgs.addAll(
"-Xcontext-receivers",
"-Xcontext-parameters",
"-opt-in=kotlin.RequiresOptIn",
)
@@ -73,8 +72,6 @@ internal fun Project.configureCompose(commonExtension: CommonExtension<*, *, *,
}
extensions.configure<ComposeCompilerGradlePluginExtension> {
featureFlags.set(setOf(ComposeFeatureFlag.OptimizeNonSkippingGroups))
val enableMetrics = project.providers.gradleProperty("enableComposeCompilerMetrics").orNull.toBoolean()
val enableReports = project.providers.gradleProperty("enableComposeCompilerReports").orNull.toBoolean()
@@ -134,18 +134,18 @@ fun OkHttpClient.newCachelessCallWithProgress(request: Request, listener: Progre
return progressClient.newCall(request)
}
context(Json)
context(_: Json)
inline fun <reified T> Response.parseAs(): T {
return decodeFromJsonResponse(serializer(), this)
}
context(Json)
context(json: Json)
fun <T> decodeFromJsonResponse(
deserializer: DeserializationStrategy<T>,
response: Response,
): T {
return response.body.source().use {
decodeFromBufferedSource(deserializer, it)
json.decodeFromBufferedSource(deserializer, it)
}
}
@@ -73,7 +73,7 @@ class CloudflareInterceptor(
executor.execute {
webview = createWebView(originalRequest)
webview?.webViewClient = object : WebViewClientCompat() {
webview.webViewClient = object : WebViewClientCompat() {
override fun onPageFinished(view: WebView, url: String) {
fun isCloudFlareBypassed(): Boolean {
return cookieManager.get(origRequestUrl.toHttpUrl())
@@ -111,7 +111,7 @@ class CloudflareInterceptor(
}
}
webview?.loadUrl(origRequestUrl, headers)
webview.loadUrl(origRequestUrl, headers)
}
latch.awaitFor30Seconds()
@@ -7,6 +7,7 @@ import me.zhanghai.android.libarchive.ArchiveException
import java.io.InputStream
import java.nio.ByteBuffer
import kotlin.concurrent.Volatile
import mihon.core.common.archive.ArchiveEntry as MihonArchiveEntry
class ArchiveInputStream(
buffer: Long,
@@ -67,18 +68,20 @@ class ArchiveInputStream(
Archive.readFree(archive)
}
fun getNextEntry() = Archive.readNextHeader(archive).takeUnless { it == 0L }?.let { entry ->
val name = ArchiveEntry.pathnameUtf8(entry) ?: ArchiveEntry.pathname(entry)?.decodeToString() ?: return null
val isFile = ArchiveEntry.filetype(entry) == ArchiveEntry.AE_IFREG
// SY -->
val isEncrypted = ArchiveEntry.isEncrypted(entry)
// SY <--
ArchiveEntry(
name,
isFile,
fun getNextEntry(): MihonArchiveEntry? {
return Archive.readNextHeader(archive).takeUnless { it == 0L }?.let { entry ->
val name = ArchiveEntry.pathnameUtf8(entry) ?: ArchiveEntry.pathname(entry)?.decodeToString() ?: return null
val isFile = ArchiveEntry.filetype(entry) == ArchiveEntry.AE_IFREG
// SY -->
isEncrypted,
val isEncrypted = ArchiveEntry.isEncrypted(entry)
// SY <--
)
MihonArchiveEntry(
name,
isFile,
// SY -->
isEncrypted,
// SY <--
)
}
}
}
@@ -23,11 +23,11 @@ import androidx.compose.material.icons.rounded.CheckBoxOutlineBlank
import androidx.compose.material.icons.rounded.DisabledByDefault
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExposedDropdownMenuAnchorType
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
@@ -293,7 +293,7 @@ fun SelectItem(
) {
OutlinedTextField(
modifier = Modifier
.menuAnchor(MenuAnchorType.PrimaryNotEditable)
.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable)
.fillMaxWidth()
.padding(
horizontal = SettingsItemsPaddings.Horizontal,