Added URL detection in reader, improved platform URL handling, library item auto-rescan, and file association support.

This commit is contained in:
sergeych committed 2026-05-25 20:14:33 +03:00
1 parent 2e9a52f4af
commit cde4d89eed
15 files changed
+367 -48

No files matched your search

@@ -20,6 +20,7 @@ import java.awt.datatransfer.Transferable
import java.awt.datatransfer.UnsupportedFlavorException
import java.io.File
import java.io.ByteArrayInputStream
import java.net.URI
import javax.imageio.ImageIO
import java.text.SimpleDateFormat
import java.util.Date
@@ -36,6 +37,14 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
private var pendingOpenBookFile: File? = null
fun rememberPlatformOpenBookArguments(args: Array<String>) {
pendingOpenBookFile = args.asSequence()
.map(::File)
.firstOrNull { it.isFile && it.name.isSupportedBookFile() }
}
actual fun loadDefaultBookBytes(): ByteArray? {
var current = File(System.getProperty("user.dir")).absoluteFile
while (true) {
@@ -70,7 +79,26 @@ actual suspend fun copyImageToClipboard(bytes: ByteArray, mimeType: String, labe
actual fun defaultLibraryScanPath(): String? = findProjectRoot()?.let { File(it, "test_books").absolutePath }
actual suspend fun loadPlatformOpenBookRequest(): PlatformOpenBookRequest? = null
actual suspend fun loadPlatformOpenBookRequest(): PlatformOpenBookRequest? = withContext(Dispatchers.IO) {
val file = pendingOpenBookFile ?: return@withContext null
pendingOpenBookFile = null
val bytes = file.readBytes()
val importResult = openLibraryDatabase().useLibrary { db ->
LibraryScanner(db, ::appendLibraryLog).importExternalFileAndGetResult(
bytes = bytes,
displayName = file.name,
storageUri = file.absolutePath,
sizeBytes = file.length(),
lastModifiedMillis = file.lastModified(),
)
}
appendLibraryLog("platform open imported=${importResult.imported} fileId=${importResult.fileId} path=${file.absolutePath}")
PlatformOpenBookRequest(
id = importResult.fileId,
displayName = file.name,
bytes = bytes,
)
}
actual suspend fun chooseLibraryScanDirectory(): String? = withContext(Dispatchers.IO) {
val chooser = JFileChooser(defaultLibraryScanPath())
@@ -301,6 +329,15 @@ actual suspend fun viewLibraryBookFile(folder: String, fileName: String): Boolea
}.getOrDefault(false)
}
actual fun openPlatformUrl(url: String): Boolean =
runCatching {
if (!Desktop.isDesktopSupported() || !Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
return@runCatching false
}
Desktop.getDesktop().browse(URI(url))
true
}.getOrDefault(false)
private fun selectOrOpenBookFile(directory: File, file: File): Boolean {
if (isLinuxDesktop() && trySelectLinuxFile(file)) return true
if (!Desktop.isDesktopSupported()) return false
@@ -654,6 +691,9 @@ private fun runCommand(vararg command: String): String? =
}
}.getOrNull()
private fun String.isSupportedBookFile(): Boolean =
endsWith(".fb2", ignoreCase = true) || endsWith(".fb2.zip", ignoreCase = true)
private const val ActiveReadingFileIdFlag = "active_reading_file_id"
private const val ThemeModeFlag = "theme_mode"
private const val ReaderFontSettingsFlag = "reader_font_settings"
@@ -3,11 +3,14 @@ package net.sergeych.toread
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
fun main() = application {
Window(
onCloseRequest = ::exitApplication,
title = strings.appName,
) {
App()
fun main(args: Array<String>) {
rememberPlatformOpenBookArguments(args)
application {
Window(
onCloseRequest = ::exitApplication,
title = strings.appName,
) {
App()
}
}
}