diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 44f111b..1ee37bb 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -101,6 +101,19 @@ compose.desktop { targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) packageName = "net.sergeych.toread" packageVersion = "1.0.0" + + macOS { + iconFile.set(project.file("src/jvmMain/resources/icons/icon.icns")) + } + windows { + iconFile.set(project.file("src/jvmMain/resources/icons/icon.ico")) + shortcut = true + menu = true + } + linux { + iconFile.set(project.file("src/jvmMain/resources/icons/icon.png")) + shortcut = true + } } } } diff --git a/composeApp/src/androidMain/ic_launcher-playstore.png b/composeApp/src/androidMain/ic_launcher-playstore.png new file mode 100644 index 0000000..63eb80d Binary files /dev/null and b/composeApp/src/androidMain/ic_launcher-playstore.png differ diff --git a/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml b/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 66ffb4b..0000000 --- a/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/composeApp/src/androidMain/res/drawable/ic_launcher_foreground.xml b/composeApp/src/androidMain/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..44548a2 --- /dev/null +++ b/composeApp/src/androidMain/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml b/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml index bbd3e02..6f2acb4 100644 --- a/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml b/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml index bbd3e02..6f2acb4 100644 --- a/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index f69e95f..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..2a23c19 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_background.webp b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_background.webp new file mode 100644 index 0000000..cfce887 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_background.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index f69e95f..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..aad71ef Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 2257963..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..c473c12 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_background.webp b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_background.webp new file mode 100644 index 0000000..a7be543 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_background.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 2257963..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..f398e66 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 7b53c00..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..664fed5 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_background.webp b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_background.webp new file mode 100644 index 0000000..afa1395 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_background.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 7b53c00..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..93f125c Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 568881a..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..23177c4 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_background.webp b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_background.webp new file mode 100644 index 0000000..7ddedea Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_background.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 568881a..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..7a5565c Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index e0eac22..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..9caf290 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_background.webp b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_background.webp new file mode 100644 index 0000000..4e478bd Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_background.webp differ diff --git a/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index e0eac22..0000000 Binary files a/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..4af6941 Binary files /dev/null and b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/composeApp/src/commonMain/kotlin/net/sergeych/toread/App.kt b/composeApp/src/commonMain/kotlin/net/sergeych/toread/App.kt index 732e78a..9c2ea56 100644 --- a/composeApp/src/commonMain/kotlin/net/sergeych/toread/App.kt +++ b/composeApp/src/commonMain/kotlin/net/sergeych/toread/App.kt @@ -30,6 +30,7 @@ import kotlinx.coroutines.launch private const val DefaultToastDurationMillis = 1_600L private const val DeleteUndoDurationMillis = 5_000L +private const val BackgroundLibraryPageSize = 50 private data class AppToastData( val id: Long, @@ -151,7 +152,7 @@ private fun BookReaderApp( durationMillis: Long, ) -> Unit, ) { - var state by remember { mutableStateOf(AppState.LoadingLibrary) } + var state by remember { mutableStateOf(AppState.LoadingStartup) } var activeScan by remember { mutableStateOf(null) } var scanJob by remember { mutableStateOf(null) } var pendingDelete by remember { mutableStateOf(null) } @@ -165,6 +166,34 @@ private fun BookReaderApp( state = loadStartupState() } + val activeBookState = when (val current = state) { + is AppState.Reader -> current.fileId to current.libraryItems.isEmpty() + is AppState.BookInfo -> current.fileId to current.libraryItems.isEmpty() + else -> null + } + LaunchedEffect(activeBookState?.first, activeBookState?.second) { + val (fileId, needsLibraryItems) = activeBookState ?: return@LaunchedEffect + if (!needsLibraryItems) return@LaunchedEffect + runCatching { loadLibraryItemsPage(BackgroundLibraryPageSize, 0) } + .onSuccess { items -> + state = when (val current = state) { + is AppState.Reader -> + if (current.fileId == fileId && current.libraryItems.isEmpty()) { + current.copy(libraryItems = items) + } else { + current + } + is AppState.BookInfo -> + if (current.fileId == fileId && current.libraryItems.isEmpty()) { + current.copy(libraryItems = items) + } else { + current + } + else -> current + } + } + } + fun commitPendingDelete(delete: PendingLibraryDelete) { scope.launch { val result = deleteLibraryBook(delete.request.fileId, delete.request.title) @@ -238,18 +267,18 @@ private fun BookReaderApp( ) is AppState.Reader -> { scope.launch { saveActiveReadingFileId(null) } - AppState.Library(emptyList(), current.scanPath, current.message) + AppState.Library(current.libraryItems, current.scanPath, current.message) } is AppState.Scan -> AppState.Library(current.items, current.scanPath, current.message) - is AppState.Error -> AppState.LoadingLibrary - is AppState.Library, AppState.LoadingLibrary -> current + is AppState.Error -> AppState.LoadingStartup + is AppState.Library, AppState.LoadingStartup -> current } } val navigationDepth = when (state) { is AppState.BookInfo -> 2 is AppState.Error, is AppState.Reader, is AppState.Scan -> 1 - is AppState.Library, AppState.LoadingLibrary -> 0 + is AppState.Library, AppState.LoadingStartup -> 0 } + if (imageViewer != null) 1 else 0 PlatformBackHandler( @@ -291,7 +320,7 @@ private fun BookReaderApp( } else { AppState.Library(current.items, path, message) } - AppState.LoadingLibrary -> loadLibraryState(message, path) + AppState.LoadingStartup -> loadLibraryState(message, path) is AppState.Reader -> current.copy(message = message) is AppState.BookInfo -> current.copy(message = message) is AppState.Error -> current @@ -300,7 +329,7 @@ private fun BookReaderApp( } when (val current = state) { - AppState.LoadingLibrary -> LoadingScreen("Opening library") + AppState.LoadingStartup -> LoadingScreen("Opening book") is AppState.Library -> LibraryScreen( state = current, activeScan = activeScan, diff --git a/composeApp/src/commonMain/kotlin/net/sergeych/toread/AppState.kt b/composeApp/src/commonMain/kotlin/net/sergeych/toread/AppState.kt index 636c015..9665adc 100644 --- a/composeApp/src/commonMain/kotlin/net/sergeych/toread/AppState.kt +++ b/composeApp/src/commonMain/kotlin/net/sergeych/toread/AppState.kt @@ -4,7 +4,7 @@ import net.sergeych.toread.fb2.Fb2Book import net.sergeych.toread.fb2.Fb2Format internal sealed interface AppState { - data object LoadingLibrary : AppState + data object LoadingStartup : AppState data class Library( val items: List, val scanPath: String, @@ -37,39 +37,40 @@ internal sealed interface AppState { } internal suspend fun loadStartupState(): AppState { - val library = loadLibraryState() - if (library !is AppState.Library) return library + val scanPath = try { + defaultLibraryScanPath().orEmpty() + } catch (t: Throwable) { + return AppState.Error(t.message ?: "Could not open library.") + } loadPlatformOpenBookRequest()?.let { request -> return runCatching { AppState.Reader( fileId = request.id, book = Fb2Format.parse(request.bytes, request.displayName), - libraryItems = library.items, - scanPath = library.scanPath, - message = library.message, + libraryItems = emptyList(), + scanPath = scanPath, ) }.getOrElse { - AppState.Library(library.items, library.scanPath, it.message ?: "Could not open ${request.displayName}.") + AppState.Library(emptyList(), scanPath, it.message ?: "Could not open ${request.displayName}.") } } - val activeFileId = loadActiveReadingFileId() ?: return library + val activeFileId = loadActiveReadingFileId() ?: return AppState.Library(emptyList(), scanPath) val item = loadLibraryItem(activeFileId) if (item == null) { saveActiveReadingFileId(null) - return library + return AppState.Library(emptyList(), scanPath) } return runCatching { val bytes = openLibraryBook(activeFileId) ?: error("Book file is not available.") AppState.Reader( fileId = activeFileId, book = Fb2Format.parse(bytes, item.storageUri ?: item.title), - libraryItems = library.items, - scanPath = library.scanPath, - message = library.message, + libraryItems = emptyList(), + scanPath = scanPath, ) }.getOrElse { saveActiveReadingFileId(null) - AppState.Library(library.items, library.scanPath, it.message ?: "Could not reopen last book.") + AppState.Library(emptyList(), scanPath, it.message ?: "Could not reopen last book.") } } diff --git a/composeApp/src/jvmMain/resources/icons/icon.icns b/composeApp/src/jvmMain/resources/icons/icon.icns new file mode 100644 index 0000000..9868b43 Binary files /dev/null and b/composeApp/src/jvmMain/resources/icons/icon.icns differ diff --git a/composeApp/src/jvmMain/resources/icons/icon.ico b/composeApp/src/jvmMain/resources/icons/icon.ico new file mode 100644 index 0000000..0b1363a Binary files /dev/null and b/composeApp/src/jvmMain/resources/icons/icon.ico differ diff --git a/composeApp/src/jvmMain/resources/icons/icon.png b/composeApp/src/jvmMain/resources/icons/icon.png new file mode 100644 index 0000000..a9d7e14 Binary files /dev/null and b/composeApp/src/jvmMain/resources/icons/icon.png differ diff --git a/image_src/icon-app-large.svg b/image_src/icon-app-large.svg new file mode 100644 index 0000000..f447c37 --- /dev/null +++ b/image_src/icon-app-large.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/image_src/icon-app.svg b/image_src/icon-app.svg index 96896f3..a1d3aaf 100644 --- a/image_src/icon-app.svg +++ b/image_src/icon-app.svg @@ -1,65 +1,264 @@ - - - - - - + + + + + + + + - - + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TOREAD - - E-READER - - + + + + + + + + + + + + + + + + + diff --git a/image_src/playstore-icon.png b/image_src/playstore-icon.png new file mode 100644 index 0000000..a9d7e14 Binary files /dev/null and b/image_src/playstore-icon.png differ