diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 9c48a7e8..cb7f95aa 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -22,5 +22,10 @@
+
+
\ No newline at end of file
diff --git a/android/src/main/java/ca/gosyer/jui/android/App.kt b/android/src/main/java/ca/gosyer/jui/android/App.kt
index 9fe213b8..4bc5f2e1 100644
--- a/android/src/main/java/ca/gosyer/jui/android/App.kt
+++ b/android/src/main/java/ca/gosyer/jui/android/App.kt
@@ -21,9 +21,9 @@ class App : Application(), DefaultLifecycleObserver {
override fun onCreate() {
super.onCreate()
- /*if (BuildConfig.DEBUG) {
+ if (BuildConfig.DEBUG) {
System.setProperty("kotlinx.coroutines.debug", "on")
- }*/
+ }
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
diff --git a/android/src/main/java/ca/gosyer/jui/android/ReaderActivity.kt b/android/src/main/java/ca/gosyer/jui/android/ReaderActivity.kt
new file mode 100644
index 00000000..a1a54039
--- /dev/null
+++ b/android/src/main/java/ca/gosyer/jui/android/ReaderActivity.kt
@@ -0,0 +1,75 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package ca.gosyer.jui.android
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.appcompat.app.AppCompatActivity
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.input.key.KeyEvent
+import androidx.compose.ui.input.key.NativeKeyEvent
+import androidx.compose.ui.input.key.key
+import androidx.lifecycle.lifecycleScope
+import ca.gosyer.ui.AppComponent
+import ca.gosyer.ui.base.theme.AppTheme
+import ca.gosyer.ui.reader.ReaderMenu
+import ca.gosyer.ui.reader.supportedKeyList
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.launch
+
+class ReaderActivity : AppCompatActivity() {
+
+ companion object {
+ fun newIntent(context: Context, mangaId: Long, chapterIndex: Int): Intent {
+ return Intent(context, ReaderActivity::class.java).apply {
+ putExtra("manga", mangaId)
+ putExtra("chapter", chapterIndex)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ }
+ }
+ }
+
+ private val hotkeyFlow = MutableSharedFlow()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val hooks = AppComponent.getInstance(applicationContext).uiComponent.getHooks()
+
+ val mangaId = intent.extras!!.getLong("manga", -1)
+ val chapterIndex = intent.extras!!.getInt("chapter", -1)
+ if (mangaId == -1L || chapterIndex == -1) {
+ finish()
+ return
+ }
+
+ setContent {
+ CompositionLocalProvider(
+ *hooks
+ ) {
+ AppTheme {
+ ReaderMenu(chapterIndex, mangaId, hotkeyFlow)
+ }
+ }
+ }
+ }
+
+ override fun onKeyUp(keyCode: Int, event: android.view.KeyEvent?): Boolean {
+ event ?: super.onKeyUp(keyCode, event)
+ val composeKeyEvent = KeyEvent(event as NativeKeyEvent)
+ lifecycleScope.launch {
+ hotkeyFlow.emit(composeKeyEvent)
+ }
+
+ return if (composeKeyEvent.key in supportedKeyList) {
+ true
+ } else {
+ super.onKeyUp(keyCode, event)
+ }
+ }
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt
index 6d5e4907..f2637049 100644
--- a/buildSrc/src/main/kotlin/Config.kt
+++ b/buildSrc/src/main/kotlin/Config.kt
@@ -13,5 +13,5 @@ object Config {
val desktopJvmTarget = JavaVersion.VERSION_16
val androidJvmTarget = JavaVersion.VERSION_11
- const val androidDev = true
+ const val androidDev = false
}
\ No newline at end of file
diff --git a/presentation/src/androidMain/kotlin/ca/gosyer/ui/reader/AndroidReaderMenu.kt b/presentation/src/androidMain/kotlin/ca/gosyer/ui/reader/AndroidReaderMenu.kt
new file mode 100644
index 00000000..e508844c
--- /dev/null
+++ b/presentation/src/androidMain/kotlin/ca/gosyer/ui/reader/AndroidReaderMenu.kt
@@ -0,0 +1,31 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package ca.gosyer.ui.reader
+
+import android.content.Context
+import android.content.Intent
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+
+actual class ReaderLauncher(private val context: Context) {
+ actual fun launch(
+ chapterIndex: Int,
+ mangaId: Long
+ ) {
+ Intent(context, Class.forName("ca.gosyer.jui.android.ReaderActivity")).apply {
+ putExtra("manga", mangaId)
+ putExtra("chapter", chapterIndex)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ }.let(context::startActivity)
+ }
+}
+@Composable
+actual fun rememberReaderLauncher(): ReaderLauncher {
+ val context = LocalContext.current
+ return remember(context) { ReaderLauncher(context) }
+}
\ No newline at end of file
diff --git a/presentation/src/androidMain/kotlin/ca/gosyer/ui/reader/openReaderMenu.kt b/presentation/src/androidMain/kotlin/ca/gosyer/ui/reader/openReaderMenu.kt
deleted file mode 100644
index 81e36aac..00000000
--- a/presentation/src/androidMain/kotlin/ca/gosyer/ui/reader/openReaderMenu.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package ca.gosyer.ui.reader
-
-actual fun openReaderMenu(chapterIndex: Int, mangaId: Long) {
-}
\ No newline at end of file
diff --git a/presentation/src/desktopMain/kotlin/ca/gosyer/ui/reader/DesktopReaderMenu.kt b/presentation/src/desktopMain/kotlin/ca/gosyer/ui/reader/DesktopReaderMenu.kt
index 4c2f3404..da247e52 100644
--- a/presentation/src/desktopMain/kotlin/ca/gosyer/ui/reader/DesktopReaderMenu.kt
+++ b/presentation/src/desktopMain/kotlin/ca/gosyer/ui/reader/DesktopReaderMenu.kt
@@ -6,6 +6,7 @@
package ca.gosyer.ui.reader
+import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
@@ -28,8 +29,21 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
+actual class ReaderLauncher {
+ actual fun launch(
+ chapterIndex: Int,
+ mangaId: Long
+ ) {
+ openReaderMenu(chapterIndex, mangaId)
+ }
+}
+@Composable
+actual fun rememberReaderLauncher(): ReaderLauncher {
+ return remember { ReaderLauncher() }
+}
+
@OptIn(DelicateCoroutinesApi::class)
-actual fun openReaderMenu(chapterIndex: Int, mangaId: Long) {
+fun openReaderMenu(chapterIndex: Int, mangaId: Long) {
val windowSettings = AppComponent.getInstance().dataComponent.uiPreferences
.readerWindow()
val (
diff --git a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/manga/components/MangaScreenContent.kt b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/manga/components/MangaScreenContent.kt
index 9ab6b346..93b7641c 100644
--- a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/manga/components/MangaScreenContent.kt
+++ b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/manga/components/MangaScreenContent.kt
@@ -6,7 +6,6 @@
package ca.gosyer.ui.manga.components
-import ca.gosyer.ui.base.components.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
@@ -15,7 +14,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
-import ca.gosyer.ui.base.components.rememberScrollbarAdapter
import androidx.compose.material.Scaffold
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Favorite
@@ -32,9 +30,11 @@ import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Manga
import ca.gosyer.i18n.MR
import ca.gosyer.ui.base.chapter.ChapterDownloadItem
+import ca.gosyer.ui.base.components.VerticalScrollbar
+import ca.gosyer.ui.base.components.rememberScrollbarAdapter
import ca.gosyer.ui.base.navigation.ActionItem
import ca.gosyer.ui.base.navigation.Toolbar
-import ca.gosyer.ui.reader.openReaderMenu
+import ca.gosyer.ui.reader.rememberReaderLauncher
import ca.gosyer.uicore.components.ErrorScreen
import ca.gosyer.uicore.components.LoadingScreen
import ca.gosyer.uicore.resources.stringResource
@@ -71,6 +71,7 @@ fun MangaScreenContent(
categoryDialogState.show()
}
}
+ val readerLauncher = rememberReaderLauncher()
Scaffold(
topBar = {
@@ -104,7 +105,7 @@ fun MangaScreenContent(
ChapterItem(
chapter,
dateTimeFormatter::format,
- onClick = { openReaderMenu(it, manga.id) },
+ onClick = { readerLauncher.launch(it, manga.id) },
toggleRead = toggleRead,
toggleBookmarked = toggleBookmarked,
markPreviousAsRead = markPreviousRead,
diff --git a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt
index 6c09e165..964003ca 100644
--- a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt
+++ b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt
@@ -78,7 +78,14 @@ val supportedKeyList = listOf(
Key.DirectionRight
)
-expect fun openReaderMenu(chapterIndex: Int, mangaId: Long)
+expect class ReaderLauncher {
+ fun launch(
+ chapterIndex: Int,
+ mangaId: Long
+ )
+}
+@Composable
+expect fun rememberReaderLauncher(): ReaderLauncher
@Composable
fun ReaderMenu(
@@ -106,13 +113,6 @@ fun ReaderMenu(
val currentPage by vm.currentPage.collectAsState()
val currentPageOffset by vm.currentPageOffset.collectAsState()
- fun hotkey(block: () -> Unit): (KeyEvent) -> Boolean {
- return {
- block()
- true
- }
- }
-
LaunchedEffect(hotkeyFlow) {
hotkeyFlow.collectLatest {
when (it.key) {
diff --git a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt
index adedf844..3e004b86 100644
--- a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt
+++ b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt
@@ -6,6 +6,7 @@
package ca.gosyer.ui.reader
+import ca.gosyer.core.lang.launchDefault
import ca.gosyer.core.lang.throwIfCancellation
import ca.gosyer.core.logging.CKLogger
import ca.gosyer.core.prefs.getAsFlow
@@ -27,7 +28,6 @@ import ca.gosyer.uicore.prefs.asStateIn
import ca.gosyer.uicore.vm.ContextWrapper
import ca.gosyer.uicore.vm.ViewModel
import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -96,9 +96,11 @@ class ReaderMenuViewModel @Inject constructor(
}
fun init() {
- scope.launch(Dispatchers.Default) {
- initManga(params.mangaId)
- initChapters(params.mangaId, params.chapterIndex)
+ scope.launchDefault {
+ runCatching {
+ initManga(params.mangaId)
+ initChapters(params.mangaId, params.chapterIndex)
+ }
}
}
@@ -147,7 +149,7 @@ class ReaderMenuViewModel @Inject constructor(
}
fun setMangaReaderMode(mode: String) {
- scope.launch(Dispatchers.Default) {
+ scope.launchDefault {
_manga.value?.updateRemote(
mangaHandler,
mode
@@ -157,8 +159,8 @@ class ReaderMenuViewModel @Inject constructor(
}
fun prevChapter() {
- scope.launch(Dispatchers.Default) {
- val prevChapter = previousChapter.value ?: return@launch
+ scope.launchDefault {
+ val prevChapter = previousChapter.value ?: return@launchDefault
try {
_state.value = ReaderChapter.State.Wait
sendProgress()
@@ -170,8 +172,8 @@ class ReaderMenuViewModel @Inject constructor(
}
fun nextChapter() {
- scope.launch(Dispatchers.Default) {
- val nextChapter = nextChapter.value ?: return@launch
+ scope.launchDefault {
+ val nextChapter = nextChapter.value ?: return@launchDefault
try {
_state.value = ReaderChapter.State.Wait
sendProgress()
@@ -205,7 +207,7 @@ class ReaderMenuViewModel @Inject constructor(
)
val pages = loader.loadChapter(chapter)
viewerChapters.currChapter.value = chapter
- scope.launch(Dispatchers.Default) {
+ scope.launchDefault {
val chapters = try {
chapterHandler.getChapters(mangaId)
} catch (e: Exception) {
@@ -265,7 +267,7 @@ class ReaderMenuViewModel @Inject constructor(
fun sendProgress(chapter: Chapter? = this.chapter.value?.chapter, lastPageRead: Int = currentPage.value) {
chapter ?: return
if (chapter.read) return
- GlobalScope.launch {
+ GlobalScope.launchDefault {
chapterHandler.updateChapter(chapter.mangaId, chapter.index, lastPageRead = lastPageRead)
}
}
@@ -276,7 +278,7 @@ class ReaderMenuViewModel @Inject constructor(
@OptIn(DelicateCoroutinesApi::class)
private fun updateLastPageReadOffset(chapter: Chapter, offset: Int) {
- GlobalScope.launch {
+ GlobalScope.launchDefault {
chapter.updateRemote(chapterHandler, offset)
}
}
diff --git a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/updates/UpdatesScreen.kt b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/updates/UpdatesScreen.kt
index 5832ef9d..2c5c4ba2 100644
--- a/presentation/src/jvmMain/kotlin/ca/gosyer/ui/updates/UpdatesScreen.kt
+++ b/presentation/src/jvmMain/kotlin/ca/gosyer/ui/updates/UpdatesScreen.kt
@@ -9,7 +9,7 @@ package ca.gosyer.ui.updates
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import ca.gosyer.ui.manga.MangaScreen
-import ca.gosyer.ui.reader.openReaderMenu
+import ca.gosyer.ui.reader.rememberReaderLauncher
import ca.gosyer.ui.updates.components.UpdatesScreenContent
import ca.gosyer.uicore.vm.viewModel
import cafe.adriel.voyager.core.screen.Screen
@@ -26,11 +26,12 @@ class UpdatesScreen : Screen {
override fun Content() {
val vm = viewModel()
val navigator = LocalNavigator.currentOrThrow
+ val readerLauncher = rememberReaderLauncher()
UpdatesScreenContent(
isLoading = vm.isLoading.collectAsState().value,
updates = vm.updates.collectAsState().value,
loadNextPage = vm::loadNextPage,
- openChapter = ::openReaderMenu,
+ openChapter = readerLauncher::launch,
openManga = { navigator push MangaScreen(it) },
downloadChapter = vm::downloadChapter,
deleteDownloadedChapter = vm::deleteDownloadedChapter,