mirror of
https://github.com/chmouel/liseur.git
synced 2026-10-19 09:13:36 +00:00
fix: restore an orphaned book when its file is picked again
Removing a watched folder kept an uploaded book on the shelf but left it with no readable file. Picking that same file again only reported it as already shelved, and the dialog's Open button did nothing. Now picking the file, or sharing it in from another app, gives the entry its readable copy back, and the book opens straight away with the reader's place and marks intact. Fixes #207
This commit is contained in:
parent
4608c6ebf2
commit
5cc733ddf3
3 changed files with 45 additions and 9 deletions
|
|
@ -50,6 +50,12 @@ data class Book(
|
|||
val source: String?,
|
||||
@ColumnInfo(name = "added_at") val addedAt: Long,
|
||||
@ColumnInfo(name = "last_opened_at") val lastOpenedAt: Long?,
|
||||
/**
|
||||
* A URI this app can open on its own, or null: a downloaded copy in
|
||||
* the app's own storage, or a hand-picked document whose read grant
|
||||
* was persisted when a re-picked file restored an orphaned row
|
||||
* (issue #207).
|
||||
*/
|
||||
@ColumnInfo(name = "local_uri") val localUri: String? = null,
|
||||
@ColumnInfo(name = "remote_uuid") val remoteUuid: String? = null,
|
||||
@ColumnInfo(name = "remote_book_id") val remoteBookId: Int? = null,
|
||||
|
|
|
|||
|
|
@ -62,13 +62,13 @@ class BookRemoval(
|
|||
.filter { (it.remoteUuid != null || it.localUri != null) && it.url !in homed }
|
||||
.forEach { book ->
|
||||
// An uploaded local book keeps its stable URL and server
|
||||
// identity, and a downloaded one its copy in the app's
|
||||
// own storage, but the released folder no longer makes
|
||||
// identity, and one with its own openable copy keeps
|
||||
// it, but the released folder no longer makes
|
||||
// the folder's file available.
|
||||
bookDao.setSource(book.url, null)
|
||||
// A copy in the app's own storage is not the folder's to
|
||||
// take away: only a book that was readable *through* the
|
||||
// folder loses its file along with it.
|
||||
// A copy the app can open on its own is not the
|
||||
// folder's to take away: only a book that was readable
|
||||
// *through* the folder loses its file along with it.
|
||||
if (book.remoteUuid != null && book.localUri == null) {
|
||||
bookDao.setDownloadState(book.url, DownloadState.REMOTE, null)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,10 +203,25 @@ class LocalLibraryRepository(
|
|||
* a watched folder has two spellings and matching on the URL alone
|
||||
* shelved it twice (issue #147). What it is, rather than what it is
|
||||
* called, decides.
|
||||
*
|
||||
* It may also be one the library remembers but can no longer open:
|
||||
* removing a watched folder keeps an uploaded book's row (issue
|
||||
* #207) with no `source` and no `localUri`. Picking that file again
|
||||
* is asking for it back, and the picked URI — whose grant the
|
||||
* caller has already persisted — becomes the row's [Book.localUri],
|
||||
* under the URL it has always had, which is where its place and its
|
||||
* marks are.
|
||||
*/
|
||||
suspend fun importBook(uri: Uri): ImportResult = importLock.withLock {
|
||||
val url = uri.toAbsoluteUrl() ?: return@withLock ImportResult.Failed
|
||||
alreadyShelved(url)?.let { return@withLock shelveAgainOrReport(it) }
|
||||
alreadyShelved(url)?.let { book ->
|
||||
if (book.openableUrl == null) {
|
||||
if (book.hidden) unhide(book.url)
|
||||
bookDao.setDownloadState(book.url, DownloadState.DOWNLOADED, url.toString())
|
||||
return@withLock ImportResult.Added(bookDao.getByUrl(book.url) ?: book)
|
||||
}
|
||||
return@withLock shelveAgainOrReport(book)
|
||||
}
|
||||
indexBook(url, source = null)
|
||||
?.let { ImportResult.Added(it) }
|
||||
?: ImportResult.Failed
|
||||
|
|
@ -311,11 +326,26 @@ class LocalLibraryRepository(
|
|||
// A book arriving from a file manager is very often one the
|
||||
// library already has under the spelling a folder scan gave it,
|
||||
// so ask what the file is and not only what it is called.
|
||||
alreadyShelved(incoming)?.let {
|
||||
alreadyShelved(incoming)?.let { book ->
|
||||
// Sharing in a book that was taken off the shelf asks for it
|
||||
// back just as plainly as picking it does.
|
||||
if (it.hidden) unhide(it.url)
|
||||
return@withLock bookDao.getByUrl(it.url) ?: it
|
||||
if (book.hidden) unhide(book.url)
|
||||
// So does sharing in one orphaned by folder removal (issue
|
||||
// #207): a durable spelling of the incoming file becomes its
|
||||
// localUri, by the same persist-or-copy rule as a new book.
|
||||
if (book.openableUrl == null) {
|
||||
val keepsWorking = incoming.toString().startsWith("file:") ||
|
||||
persistPermission(uri)
|
||||
val localUri = if (keepsWorking) {
|
||||
incoming.toString()
|
||||
} else {
|
||||
copyIntoLibrary(uri)?.toString()
|
||||
}
|
||||
if (localUri != null) {
|
||||
bookDao.setDownloadState(book.url, DownloadState.DOWNLOADED, localUri)
|
||||
}
|
||||
}
|
||||
return@withLock bookDao.getByUrl(book.url) ?: book
|
||||
}
|
||||
|
||||
// A real file is already as permanent as the library is, and a
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue