Home and Library screen update (#101)
* Added support for filtering file types in synced folders * Added support for custom file names and enhanced file information dialog * added feedback option in the homescreen drawer * Implemented a limit for number of recent files displayed on the home screen
This commit is contained in:
parent
9842aea9b1
commit
ddcd253c7b
13 changed files with 637 additions and 734 deletions
|
|
@ -148,7 +148,7 @@ data class DeviceLimitReachedState(
|
|||
)
|
||||
|
||||
data class SyncedFolder(
|
||||
val uriString: String, val name: String, val lastScanTime: Long
|
||||
val uriString: String, val name: String, val lastScanTime: Long, val allowedFileTypes: Set<FileType> = FileType.entries.toSet()
|
||||
)
|
||||
|
||||
data class Shelf(val name: String, val books: List<RecentFileItem>) {
|
||||
|
|
@ -227,6 +227,7 @@ data class ReaderScreenState(
|
|||
val pinnedHomeBookIds: Set<String> = emptySet(),
|
||||
val pinnedLibraryBookIds: Set<String> = emptySet(),
|
||||
val libraryFilters: LibraryFilters = LibraryFilters(),
|
||||
val recentFilesLimit: Int = 0,
|
||||
)
|
||||
|
||||
open class MainViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
|
@ -324,7 +325,8 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
)
|
||||
else null,
|
||||
pinnedHomeBookIds = prefs.getStringSet(KEY_PINNED_HOME, emptySet()) ?: emptySet(),
|
||||
pinnedLibraryBookIds = prefs.getStringSet(KEY_PINNED_LIBRARY, emptySet()) ?: emptySet()
|
||||
pinnedLibraryBookIds = prefs.getStringSet(KEY_PINNED_LIBRARY, emptySet()) ?: emptySet(),
|
||||
recentFilesLimit = prefs.getInt(KEY_RECENT_FILES_LIMIT, 0)
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -377,7 +379,8 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
val visibleRecentFiles = sortFiles(baseVisibleFiles.filter { it.isRecent }).let { list ->
|
||||
val pinned = list.filter { it.bookId in internalState.pinnedHomeBookIds }
|
||||
val unpinned = list.filter { it.bookId !in internalState.pinnedHomeBookIds }
|
||||
pinned + unpinned
|
||||
val combined = pinned + unpinned
|
||||
if (internalState.recentFilesLimit > 0) combined.take(internalState.recentFilesLimit) else combined
|
||||
}
|
||||
|
||||
val validContextualItems = internalState.contextualActionItems.filter { contextItem ->
|
||||
|
|
@ -783,7 +786,7 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
|
||||
fun deleteBookPermanently(bookId: String, onDeleted: () -> Unit = {}) {
|
||||
viewModelScope.launch {
|
||||
val item = recentFilesRepository.getFileByBookId(bookId) ?: return@launch
|
||||
@Suppress("UnusedVariable", "Unused") val item = recentFilesRepository.getFileByBookId(bookId) ?: return@launch
|
||||
|
||||
Timber.d("Deleting book permanently from reader: $bookId")
|
||||
|
||||
|
|
@ -1384,7 +1387,7 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
val oldTime = prefs.getLong(KEY_LAST_FOLDER_SCAN_TIME, 0L)
|
||||
if (oldUri != null) {
|
||||
val name = getDisplayPathFromUri(appContext, oldUri)
|
||||
val migrated = SyncedFolder(oldUri, name, oldTime)
|
||||
val migrated = SyncedFolder(oldUri, name, oldTime, FileType.entries.toSet())
|
||||
folders.add(migrated)
|
||||
saveSyncedFoldersToPrefs(folders)
|
||||
|
||||
|
|
@ -1398,11 +1401,25 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
val jsonArray = JSONArray(jsonString)
|
||||
for (i in 0 until jsonArray.length()) {
|
||||
val obj = jsonArray.getJSONObject(i)
|
||||
|
||||
val allowedFileTypes = mutableSetOf<FileType>()
|
||||
if (obj.has("allowedFileTypes")) {
|
||||
val typesArray = obj.getJSONArray("allowedFileTypes")
|
||||
for (j in 0 until typesArray.length()) {
|
||||
try {
|
||||
allowedFileTypes.add(FileType.valueOf(typesArray.getString(j)))
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
} else {
|
||||
allowedFileTypes.addAll(FileType.entries)
|
||||
}
|
||||
|
||||
folders.add(
|
||||
SyncedFolder(
|
||||
uriString = obj.getString("uri"),
|
||||
name = obj.getString("name"),
|
||||
lastScanTime = obj.optLong("lastScanTime", 0L)
|
||||
lastScanTime = obj.optLong("lastScanTime", 0L),
|
||||
allowedFileTypes = allowedFileTypes
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1420,6 +1437,9 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
obj.put("uri", folder.uriString)
|
||||
obj.put("name", folder.name)
|
||||
obj.put("lastScanTime", folder.lastScanTime)
|
||||
val typesArray = JSONArray()
|
||||
folder.allowedFileTypes.forEach { typesArray.put(it.name) }
|
||||
obj.put("allowedFileTypes", typesArray)
|
||||
jsonArray.put(obj)
|
||||
}
|
||||
prefs.edit { putString(KEY_SYNCED_FOLDERS_JSON, jsonArray.toString()) }
|
||||
|
|
@ -1446,7 +1466,7 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
)
|
||||
|
||||
val name = getDisplayPathFromUri(appContext, folderUri.toString())
|
||||
val newFolder = SyncedFolder(folderUri.toString(), name, 0L)
|
||||
val newFolder = SyncedFolder(folderUri.toString(), name, 0L, FileType.entries.toSet())
|
||||
val newStats = currentFolders + newFolder
|
||||
|
||||
saveSyncedFoldersToPrefs(newStats)
|
||||
|
|
@ -1578,6 +1598,37 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
}
|
||||
}
|
||||
|
||||
fun updateFolderFilters(folder: SyncedFolder, newFilters: Set<FileType>) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val currentFolders = _internalState.value.syncedFolders.toMutableList()
|
||||
val index = currentFolders.indexOfFirst { it.uriString == folder.uriString }
|
||||
if (index != -1) {
|
||||
val updatedFolder = folder.copy(allowedFileTypes = newFilters)
|
||||
currentFolders[index] = updatedFolder
|
||||
saveSyncedFoldersToPrefs(currentFolders)
|
||||
_internalState.update { it.copy(syncedFolders = currentFolders) }
|
||||
|
||||
val filesToRemove = recentFilesRepository.getFilesBySourceFolder(folder.uriString)
|
||||
.filter { it.type !in newFilters }
|
||||
|
||||
if (filesToRemove.isNotEmpty()) {
|
||||
Timber.d("Removing ${filesToRemove.size} files that no longer match the filter for folder ${folder.name}")
|
||||
val idsToRemove = filesToRemove.map { it.bookId }
|
||||
|
||||
idsToRemove.forEach { bookId ->
|
||||
pdfTextRepository.clearBookText(bookId)
|
||||
clearImportedFileCache(bookId)
|
||||
}
|
||||
recentFilesRepository.deleteFilePermanently(idsToRemove)
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
scanSyncedFolder()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun disconnectAllSyncedFolders() {
|
||||
viewModelScope.launch {
|
||||
val folders = _internalState.value.syncedFolders
|
||||
|
|
@ -2374,6 +2425,11 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
}
|
||||
}
|
||||
|
||||
fun setRecentFilesLimit(limit: Int) {
|
||||
_internalState.update { it.copy(recentFilesLimit = limit) }
|
||||
prefs.edit { putInt(KEY_RECENT_FILES_LIMIT, limit) }
|
||||
}
|
||||
|
||||
fun setSortOrder(sortOrder: SortOrder) {
|
||||
_internalState.update { it.copy(sortOrder = sortOrder) }
|
||||
prefs.edit { putString(KEY_SORT_ORDER, sortOrder.name) }
|
||||
|
|
@ -3799,6 +3855,26 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
}
|
||||
}
|
||||
|
||||
fun updateCustomName(bookId: String, newName: String?) {
|
||||
viewModelScope.launch {
|
||||
val item = recentFilesRepository.getFileByBookId(bookId)
|
||||
if (item != null) {
|
||||
val updatedItem = item.copy(customName = newName, lastModifiedTimestamp = System.currentTimeMillis())
|
||||
recentFilesRepository.addRecentFile(updatedItem)
|
||||
|
||||
if (uiState.value.isSyncEnabled) {
|
||||
uploadSingleBookMetadata(updatedItem)
|
||||
}
|
||||
|
||||
if (updatedItem.sourceFolderUri != null) {
|
||||
launch(Dispatchers.IO) {
|
||||
recentFilesRepository.syncLocalMetadataToFolder(bookId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_SORT_ORDER = "sort_order"
|
||||
internal const val KEY_SHELVES = "shelf_names"
|
||||
|
|
@ -3817,5 +3893,6 @@ open class MainViewModel(application: Application) : AndroidViewModel(applicatio
|
|||
private const val MAX_FOLDER_LIMIT = 3
|
||||
internal const val KEY_PINNED_HOME = "pinned_home_books"
|
||||
internal const val KEY_PINNED_LIBRARY = "pinned_library_books"
|
||||
private const val KEY_RECENT_FILES_LIMIT = "recent_files_limit"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue