Compare commits

...

7 Commits

Author SHA1 Message Date
renovate[bot]
ebee275110 fix(deps): update dependency io.kotest:kotest-assertions-core to v5.8.1 (#528)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-17 20:45:26 +06:00
renovate[bot]
015d9b3bd0 fix(deps): update dependency com.squareup.okio:okio to v3.9.0 (#529)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-17 20:45:09 +06:00
AntsyLich
f2ccfb0817 Typo in r0adkll/sign-android-release SHA 2024-03-17 20:25:51 +06:00
AntsyLich
1b60c5f0f4 Check for dependency update every Friday 2024-03-17 20:22:08 +06:00
AntsyLich
0a91b57f67 Use SHA for GitHub actions version 2024-03-17 20:21:05 +06:00
AntsyLich
bcdf17fe27 Disable SerialVersionUIDInSerializableClass detekt rule 2024-03-17 19:44:23 +06:00
Jobobby04
a08e03f5cb Fix multiple issues regarding sources loading too late 2024-03-17 19:44:22 +06:00
19 changed files with 91 additions and 41 deletions

View File

@@ -3,7 +3,7 @@
"extends": [
"config:base"
],
"schedule": ["every sunday"],
"schedule": ["every friday"],
"labels": ["Dependencies"],
"packageRules": [
{

View File

@@ -20,22 +20,22 @@ jobs:
steps:
- name: Clone repo
uses: actions/checkout@v4
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2
uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1
- name: Dependency Review
uses: actions/dependency-review-action@v4
uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3
- name: Set up JDK
uses: actions/setup-java@v4
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
with:
java-version: 17
distribution: adopt
- name: Set up gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
- name: Build app and run unit tests
run: ./gradlew detekt assembleStandardRelease testReleaseUnitTest

View File

@@ -17,23 +17,23 @@ jobs:
steps:
- name: Clone repo
uses: actions/checkout@v4
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2
uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1
- name: Setup Android SDK
run: |
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "build-tools;29.0.3"
- name: Set up JDK
uses: actions/setup-java@v4
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
with:
java-version: 17
distribution: adopt
- name: Set up gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
- name: Build app and run unit tests
run: ./gradlew detekt assembleStandardRelease testReleaseUnitTest
@@ -48,7 +48,7 @@ jobs:
- name: Sign APK
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'mihonapp/mihon'
uses: r0adkll/sign-android-release@v1
uses: r0adkll/sign-android-release@349ebdef58775b1e0d8099458af0816dc79b6407 # v1
with:
releaseDirectory: app/build/outputs/apk/standard/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
@@ -83,7 +83,7 @@ jobs:
- name: Create Release
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'mihonapp/mihon'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2.0.4
with:
tag_name: ${{ env.VERSION_TAG }}
name: Mihon ${{ env.VERSION_TAG }}

View File

@@ -11,28 +11,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Moderate issues
uses: tachiyomiorg/issue-moderator-action@v2.6.0
uses: keiyoushi/issue-moderator-action@a017be83547db6e107431ce7575f53c1dfa3296a
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
duplicate-label: Duplicate
auto-close-rules: |
[
{
"type": "body",
"regex": ".*DELETE THIS SECTION IF YOU HAVE READ AND ACKNOWLEDGED IT.*",
"message": "The acknowledgment section was not removed."
},
{
"type": "body",
"regex": ".*\\* (Tachiyomi version|Android version|Device): \\?.*",
"message": "Requested information in the template was not filled out."
},
{
"type": "both",
"regex": "^(?!.*myanimelist.*).*(aniyomi|anime).*$",
"ignoreCase": true,
"message": "Tachiyomi does not support anime, and has no plans to support anime. In addition Tachiyomi is not affiliated with Aniyomi https://github.com/jmir1/aniyomi"
"message": "Mihon does not support anime, and has no plans to support anime. In addition Mihon is not affiliated with Aniyomi https://github.com/jmir1/aniyomi"
},
{
"type": "both",

View File

@@ -12,7 +12,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v5
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1
with:
github-token: ${{ github.token }}
issue-inactive-days: '2'

View File

@@ -0,0 +1,13 @@
package eu.kanade.core.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun ifSourcesLoaded(): Boolean {
return remember { Injekt.get<SourceManager>().isInitialized }.collectAsState().value
}

View File

@@ -18,6 +18,7 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
@@ -311,18 +312,12 @@ class DownloadCache(
}
// Try to wait until extensions and sources have loaded
var sources = getSources()
if (sources.isEmpty()) {
withTimeoutOrNull(30.seconds) {
while (!extensionManager.isInitialized) {
delay(2.seconds)
}
var sources = emptyList<Source>()
withTimeoutOrNull(30.seconds) {
extensionManager.isInitialized.first { it }
sourceManager.isInitialized.first { it }
while (extensionManager.availableExtensionsFlow.value.isNotEmpty() && sources.isEmpty()) {
delay(2.seconds)
sources = getSources()
}
}
sources = getSources()
}
val sourceMap = sources.associate { provider.getSourceDirName(it).lowercase() to it.id }

View File

@@ -16,6 +16,7 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.emptyFlow
import logcat.LogPriority
@@ -41,8 +42,8 @@ class ExtensionManager(
private val trustExtension: TrustExtension = Injekt.get(),
) {
var isInitialized = false
private set
private val _isInitialized = MutableStateFlow(false)
val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
/**
* API where all the available extensions can be found.
@@ -108,7 +109,7 @@ class ExtensionManager(
.filterIsInstance<LoadResult.Untrusted>()
.map { it.extension }
isInitialized = true
_isInitialized.value = true
}
/**

View File

@@ -9,6 +9,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
@@ -28,6 +30,9 @@ class AndroidSourceManager(
private val sourceRepository: StubSourceRepository,
) : SourceManager {
private val _isInitialized = MutableStateFlow(false)
override val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
private val downloadManager: DownloadManager by injectLazy()
private val scope = CoroutineScope(Job() + Dispatchers.IO)
@@ -60,6 +65,7 @@ class AndroidSourceManager(
}
}
sourcesMapFlow.value = mutableMap
_isInitialized.value = true
}
}

View File

@@ -31,6 +31,7 @@ import androidx.preference.forEach
import androidx.preference.getOnBindEditTextListener
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifSourcesLoaded
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.R
@@ -40,6 +41,7 @@ import eu.kanade.tachiyomi.source.sourcePreferences
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
import tachiyomi.domain.source.service.SourceManager
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.screens.LoadingScreen
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -47,6 +49,11 @@ class SourcePreferencesScreen(val sourceId: Long) : Screen() {
@Composable
override fun Content() {
if (!ifSourcesLoaded()) {
LoadingScreen()
return
}
val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow

View File

@@ -18,6 +18,7 @@ import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifSourcesLoaded
import eu.kanade.presentation.browse.BrowseSourceContent
import eu.kanade.presentation.components.SearchToolbar
import eu.kanade.presentation.util.Screen
@@ -34,6 +35,7 @@ import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.source.local.LocalSource
data class SourceSearchScreen(
@@ -44,6 +46,11 @@ data class SourceSearchScreen(
@Composable
override fun Content() {
if (!ifSourcesLoaded()) {
LoadingScreen()
return
}
val uriHandler = LocalUriHandler.current
val navigator = LocalNavigator.currentOrThrow
val scope = rememberCoroutineScope()

View File

@@ -35,6 +35,7 @@ import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifSourcesLoaded
import eu.kanade.presentation.browse.BrowseSourceContent
import eu.kanade.presentation.browse.MissingSourceScreen
import eu.kanade.presentation.browse.components.BrowseSourceToolbar
@@ -60,6 +61,7 @@ import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.source.local.LocalSource
data class BrowseSourceScreen(
@@ -73,6 +75,11 @@ data class BrowseSourceScreen(
@Composable
override fun Content() {
if (!ifSourcesLoaded()) {
LoadingScreen()
return
}
val screenModel = rememberScreenModel { BrowseSourceScreenModel(sourceId, listingQuery) }
val state by screenModel.state.collectAsState()

View File

@@ -10,6 +10,7 @@ import androidx.compose.runtime.setValue
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifSourcesLoaded
import eu.kanade.presentation.browse.GlobalSearchScreen
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
@@ -23,6 +24,11 @@ class GlobalSearchScreen(
@Composable
override fun Content() {
if (!ifSourcesLoaded()) {
LoadingScreen()
return
}
val navigator = LocalNavigator.currentOrThrow
val screenModel = rememberScreenModel {

View File

@@ -22,6 +22,7 @@ import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifSourcesLoaded
import eu.kanade.domain.manga.model.hasCustomCover
import eu.kanade.domain.manga.model.toSManga
import eu.kanade.presentation.category.components.ChangeCategoryDialog
@@ -73,6 +74,11 @@ class MangaScreen(
@Composable
override fun Content() {
if (!ifSourcesLoaded()) {
LoadingScreen()
return
}
val navigator = LocalNavigator.currentOrThrow
val context = LocalContext.current
val haptic = LocalHapticFeedback.current

View File

@@ -40,6 +40,7 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.google.android.material.elevation.SurfaceColors
import com.google.android.material.transition.platform.MaterialContainerTransform
import dev.chrisbanes.insetter.applyInsetter
import eu.kanade.core.util.ifSourcesLoaded
import eu.kanade.domain.base.BasePreferences
import eu.kanade.presentation.reader.DisplayRefreshHost
import eu.kanade.presentation.reader.OrientationSelectDialog
@@ -344,6 +345,10 @@ class ReaderActivity : BaseActivity() {
)
}
if (!ifSourcesLoaded()) {
return@setComposeContent
}
val isHttpSource = viewModel.getSource() is HttpSource
val isFullscreen by readerPreferences.fullscreen().collectAsState()
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState()

View File

@@ -47,6 +47,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
@@ -264,6 +265,7 @@ class ReaderViewModel @JvmOverloads constructor(
try {
val manga = getManga.await(mangaId)
if (manga != null) {
sourceManager.isInitialized.first { it }
mutableState.update { it.copy(manga = manga) }
if (chapterId == -1L) chapterId = initialChapterId

View File

@@ -18,5 +18,7 @@ style:
ignoreCompanionObjectPropertyDeclaration: true
ReturnCount:
excludeGuardClauses: true
SerialVersionUIDInSerializableClass:
active: false
UnusedPrivateMember:
ignoreAnnotated: [ 'Preview' ]

View File

@@ -4,10 +4,13 @@ import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import tachiyomi.domain.source.model.StubSource
interface SourceManager {
val isInitialized: StateFlow<Boolean>
val catalogueSources: Flow<List<CatalogueSource>>
fun get(sourceKey: Long): Source?

View File

@@ -22,7 +22,7 @@ okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp_ve
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp_version" }
okhttp-brotli = { module = "com.squareup.okhttp3:okhttp-brotli", version.ref = "okhttp_version" }
okhttp-dnsoverhttps = { module = "com.squareup.okhttp3:okhttp-dnsoverhttps", version.ref = "okhttp_version" }
okio = "com.squareup.okio:okio:3.8.0"
okio = "com.squareup.okio:okio:3.9.0"
conscrypt-android = "org.conscrypt:conscrypt-android:2.5.2"
@@ -89,7 +89,7 @@ sqldelight-dialects-sql = { module = "app.cash.sqldelight:sqlite-3-38-dialect",
sqldelight-gradle = { module = "app.cash.sqldelight:gradle-plugin", version.ref = "sqldelight" }
junit = "org.junit.jupiter:junit-jupiter:5.10.2"
kotest-assertions = "io.kotest:kotest-assertions-core:5.8.0"
kotest-assertions = "io.kotest:kotest-assertions-core:5.8.1"
mockk = "io.mockk:mockk:1.13.10"
voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" }