🚀 External storage support

* Added external storage (SD) support for all APIs
* Removed directory structure in Browse due to problems with Internal+External
* Optimized loading time

Resolves: #78
This commit is contained in:
Acclorite 2025-01-15 12:35:52 +02:00
parent 8956bd5134
commit 6f53811f68
54 changed files with 359 additions and 1289 deletions

View file

@ -0,0 +1,170 @@
{
"formatVersion": 1,
"database": {
"version": 9,
"identityHash": "e7887e5269c44d6066b6c71418b013fa",
"entities": [
{
"tableName": "BookEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `author` TEXT, `description` TEXT, `filePath` TEXT NOT NULL, `scrollIndex` INTEGER NOT NULL, `scrollOffset` INTEGER NOT NULL, `progress` REAL NOT NULL, `image` TEXT, `category` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "filePath",
"columnName": "filePath",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "scrollIndex",
"columnName": "scrollIndex",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "scrollOffset",
"columnName": "scrollOffset",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "progress",
"columnName": "progress",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "image",
"columnName": "image",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "category",
"columnName": "category",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "HistoryEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `bookId` INTEGER NOT NULL, `time` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "bookId",
"columnName": "bookId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "time",
"columnName": "time",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "ColorPresetEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT, `backgroundColor` INTEGER NOT NULL, `fontColor` INTEGER NOT NULL, `isSelected` INTEGER NOT NULL, `order` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "backgroundColor",
"columnName": "backgroundColor",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "fontColor",
"columnName": "fontColor",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "isSelected",
"columnName": "isSelected",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "order",
"columnName": "order",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e7887e5269c44d6066b6c71418b013fa')"
]
}
}

View file

@ -21,14 +21,12 @@ import ua.acclorite.book_story.data.parser.TextParserImpl
import ua.acclorite.book_story.data.repository.BookRepositoryImpl import ua.acclorite.book_story.data.repository.BookRepositoryImpl
import ua.acclorite.book_story.data.repository.ColorPresetRepositoryImpl import ua.acclorite.book_story.data.repository.ColorPresetRepositoryImpl
import ua.acclorite.book_story.data.repository.DataStoreRepositoryImpl import ua.acclorite.book_story.data.repository.DataStoreRepositoryImpl
import ua.acclorite.book_story.data.repository.FavoriteDirectoryRepositoryImpl
import ua.acclorite.book_story.data.repository.FileSystemRepositoryImpl import ua.acclorite.book_story.data.repository.FileSystemRepositoryImpl
import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl
import ua.acclorite.book_story.data.repository.RemoteRepositoryImpl import ua.acclorite.book_story.data.repository.RemoteRepositoryImpl
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.repository.ColorPresetRepository import ua.acclorite.book_story.domain.repository.ColorPresetRepository
import ua.acclorite.book_story.domain.repository.DataStoreRepository import ua.acclorite.book_story.domain.repository.DataStoreRepository
import ua.acclorite.book_story.domain.repository.FavoriteDirectoryRepository
import ua.acclorite.book_story.domain.repository.FileSystemRepository import ua.acclorite.book_story.domain.repository.FileSystemRepository
import ua.acclorite.book_story.domain.repository.HistoryRepository import ua.acclorite.book_story.domain.repository.HistoryRepository
import ua.acclorite.book_story.domain.repository.RemoteRepository import ua.acclorite.book_story.domain.repository.RemoteRepository
@ -79,12 +77,6 @@ abstract class RepositoryModule {
remoteRepositoryImpl: RemoteRepositoryImpl remoteRepositoryImpl: RemoteRepositoryImpl
): RemoteRepository ): RemoteRepository
@Binds
@Singleton
abstract fun bindFavoriteDirectoryRepository(
favoriteDirectoryRepositoryImpl: FavoriteDirectoryRepositoryImpl
): FavoriteDirectoryRepository
@Binds @Binds
@Singleton @Singleton
abstract fun bindBookMapper( abstract fun bindBookMapper(

View file

@ -1,10 +0,0 @@
package ua.acclorite.book_story.data.local.dto
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity
data class FavoriteDirectoryEntity(
@PrimaryKey(autoGenerate = false)
val path: String
)

View file

@ -9,7 +9,6 @@ import androidx.room.Update
import androidx.room.Upsert import androidx.room.Upsert
import ua.acclorite.book_story.data.local.dto.BookEntity import ua.acclorite.book_story.data.local.dto.BookEntity
import ua.acclorite.book_story.data.local.dto.ColorPresetEntity import ua.acclorite.book_story.data.local.dto.ColorPresetEntity
import ua.acclorite.book_story.data.local.dto.FavoriteDirectoryEntity
import ua.acclorite.book_story.data.local.dto.HistoryEntity import ua.acclorite.book_story.data.local.dto.HistoryEntity
/** /**
@ -88,16 +87,4 @@ interface BookDao {
@Query("DELETE FROM colorpresetentity") @Query("DELETE FROM colorpresetentity")
suspend fun deleteColorPresets() suspend fun deleteColorPresets()
/* - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - */
/* ------ FavoriteDirectoryEntity ----------- */
@Upsert
suspend fun insertFavoriteDirectory(favoriteDirectoryEntity: FavoriteDirectoryEntity)
@Query("SELECT EXISTS(SELECT 1 FROM favoritedirectoryentity WHERE path = :path LIMIT 1)")
suspend fun favoriteDirectoryExits(path: String): Boolean
@Delete
suspend fun deleteFavoriteDirectory(favoriteDirectoryEntity: FavoriteDirectoryEntity)
/* - - - - - - - - - - - - - - - - - - - - - - */
} }

View file

@ -11,7 +11,6 @@ import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import ua.acclorite.book_story.data.local.dto.BookEntity import ua.acclorite.book_story.data.local.dto.BookEntity
import ua.acclorite.book_story.data.local.dto.ColorPresetEntity import ua.acclorite.book_story.data.local.dto.ColorPresetEntity
import ua.acclorite.book_story.data.local.dto.FavoriteDirectoryEntity
import ua.acclorite.book_story.data.local.dto.HistoryEntity import ua.acclorite.book_story.data.local.dto.HistoryEntity
import java.io.File import java.io.File
@ -20,9 +19,8 @@ import java.io.File
BookEntity::class, BookEntity::class,
HistoryEntity::class, HistoryEntity::class,
ColorPresetEntity::class, ColorPresetEntity::class,
FavoriteDirectoryEntity::class,
], ],
version = 8, version = 9,
autoMigrations = [ autoMigrations = [
AutoMigration(1, 2), AutoMigration(1, 2),
AutoMigration(2, 3), AutoMigration(2, 3),
@ -30,7 +28,8 @@ import java.io.File
AutoMigration(4, 5), AutoMigration(4, 5),
AutoMigration(5, 6), AutoMigration(5, 6),
AutoMigration(6, 7), AutoMigration(6, 7),
AutoMigration(7, 8, spec = DatabaseHelper.MIGRATION_7_8::class) AutoMigration(7, 8, spec = DatabaseHelper.MIGRATION_7_8::class),
AutoMigration(8, 9, spec = DatabaseHelper.MIGRATION_8_9::class),
], ],
exportSchema = true exportSchema = true
) )
@ -105,4 +104,7 @@ object DatabaseHelper {
} }
} }
} }
@DeleteTable("FavoriteDirectoryEntity")
class MIGRATION_8_9 : AutoMigrationSpec
} }

View file

@ -1,35 +0,0 @@
package ua.acclorite.book_story.data.repository
import ua.acclorite.book_story.data.local.dto.FavoriteDirectoryEntity
import ua.acclorite.book_story.data.local.room.BookDao
import ua.acclorite.book_story.domain.repository.FavoriteDirectoryRepository
import javax.inject.Inject
import javax.inject.Singleton
/**
* Favorite Directory repository.
* Manages all [ua.acclorite.book_story.data.local.dto.FavoriteDirectoryEntity] related work.
*/
@Singleton
class FavoriteDirectoryRepositoryImpl @Inject constructor(
private val database: BookDao,
) : FavoriteDirectoryRepository {
/**
* Create or delete favorite directory if already exists.
*
* @param path Path to directory.
*/
override suspend fun updateFavoriteDirectory(path: String) {
if (database.favoriteDirectoryExits(path)) {
database.deleteFavoriteDirectory(
FavoriteDirectoryEntity(path)
)
return
}
database.insertFavoriteDirectory(
FavoriteDirectoryEntity(path)
)
}
}

View file

@ -1,10 +1,15 @@
package ua.acclorite.book_story.data.repository package ua.acclorite.book_story.data.repository
import android.app.Application
import android.content.Context.STORAGE_SERVICE
import android.os.Build
import android.os.Environment import android.os.Environment
import android.os.storage.StorageManager
import android.util.Log import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.data.local.room.BookDao import ua.acclorite.book_story.data.local.room.BookDao
import ua.acclorite.book_story.data.mapper.book.BookMapper
import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.data.parser.FileParser
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.domain.library.book.NullableBook import ua.acclorite.book_story.domain.library.book.NullableBook
@ -27,8 +32,8 @@ private const val GET_FILES_FROM_DEVICE = "FILES FROM DEVICE, REPO"
*/ */
@Singleton @Singleton
class FileSystemRepositoryImpl @Inject constructor( class FileSystemRepositoryImpl @Inject constructor(
private val application: Application,
private val database: BookDao, private val database: BookDao,
private val bookMapper: BookMapper,
private val fileParser: FileParser private val fileParser: FileParser
) : FileSystemRepository { ) : FileSystemRepository {
@ -39,101 +44,100 @@ class FileSystemRepositoryImpl @Inject constructor(
override suspend fun getFilesFromDevice(query: String): List<SelectableFile> { override suspend fun getFilesFromDevice(query: String): List<SelectableFile> {
Log.i(GET_FILES_FROM_DEVICE, "Getting files from device by query: \"$query\".") Log.i(GET_FILES_FROM_DEVICE, "Getting files from device by query: \"$query\".")
val existingBooks = database val existingPaths = database
.searchBooks("") .searchBooks("")
.map { bookMapper.toBook(it) } .map { it.filePath.trim() }
val supportedExtensions = Constants.provideExtensions() val supportedExtensions = Constants.provideExtensions()
/**
* Verify that a file is valid and can be shown correctly.
*/
fun File.isValid(): Boolean { fun File.isValid(): Boolean {
if (!exists()) { if (!exists() || !canRead() || !isFile) return false
return false
// First: Ensuring supported extension
supportedExtensions.any { ext ->
name.endsWith(ext, ignoreCase = true)
}.let { if (!it) return false }
// Second: Ensuring query to match
if (query.isNotBlank()) {
name.contains(query.trim(), ignoreCase = true)
.let { if (!it) return false }
} }
val isFileSupported = supportedExtensions.any { ext -> // Third: Ensuring that a file is not added already
name.endsWith( existingPaths.none { existingPath ->
ext, existingPath.equals(path.trim(), ignoreCase = true)
ignoreCase = true }.let { if (!it) return false }
)
}
if (!isFileSupported) { return true
return false
}
val isFileNotAdded = existingBooks.all {
it.filePath.lowercase().trim() != path.lowercase().trim()
}
if (!isFileNotAdded) {
return false
}
val isQuery = if (query.isEmpty()) true else name.trim().lowercase()
.contains(query.trim().lowercase())
return isQuery
} }
suspend fun File.getAllFiles(): List<SelectableFile> { /**
val filesList = mutableListOf<SelectableFile>() * Get all verified files from directory (root).
*/
fun File.getFilesFromDirectory(): List<SelectableFile> {
return walk().mapNotNull {
if (!it.isValid()) return@mapNotNull null
SelectableFile(
name = it.name,
path = it.path,
size = it.length(),
lastModified = it.lastModified(),
selected = false
)
}.toList()
}
val files = listFiles() /**
if (files != null) { * Get all storages (including SD).
for (file in files) { */
if (!file.exists()) { fun getAllStorageDirectories(): List<File> {
continue val storageDirectories = mutableListOf<File>()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val storageManager = application.getSystemService(STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes.mapNotNull { it.directory }
for (volume in storageVolumes) {
if (volume.exists() && volume.canRead() && volume.isDirectory) {
storageDirectories.add(volume)
} }
}
} else {
val internalStorage = Environment.getExternalStorageDirectory()
if (internalStorage.exists() && internalStorage.canRead() && internalStorage.isDirectory) {
storageDirectories.add(internalStorage)
}
when { val storageVolumes = File("/storage")
file.isFile -> { if (storageVolumes.exists() && storageVolumes.canRead() && storageVolumes.isDirectory) {
if (file.isValid()) { storageVolumes.listFiles()?.forEach { volume ->
filesList.add( if (
SelectableFile( volume.exists() &&
fileOrDirectory = file, volume.canRead() &&
parentDirectory = this, volume.isDirectory &&
isDirectory = false, volume != internalStorage
isFavorite = false, ) {
isSelected = false storageDirectories.add(volume)
)
)
}
}
file.isDirectory -> {
val subDirectoryFiles = file.getAllFiles()
if (subDirectoryFiles.isNotEmpty()) {
filesList.add(
SelectableFile(
fileOrDirectory = file,
parentDirectory = this,
isDirectory = true,
isFavorite = database.favoriteDirectoryExits(file.path),
isSelected = false
)
)
filesList.addAll(subDirectoryFiles)
}
} }
} }
} }
} }
return filesList return storageDirectories
} }
val rootDirectory = Environment.getExternalStorageDirectory() val storageDirectories = getAllStorageDirectories()
if ( val files = mutableListOf<SelectableFile>()
!rootDirectory.exists() ||
!rootDirectory.isDirectory || for (volume in storageDirectories) {
(Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED && files.addAll(withContext(Dispatchers.IO) { volume.getFilesFromDirectory() })
Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED_READ_ONLY)
) {
Log.e(GET_FILES_FROM_DEVICE, "Could not correctly get root directory.")
return emptyList()
} }
Log.i(GET_FILES_FROM_DEVICE, "Successfully got all matching files.") Log.i(GET_FILES_FROM_DEVICE, "Successfully got all matching files.")
return rootDirectory.getAllFiles() return files
} }
/** /**

View file

@ -1,12 +0,0 @@
package ua.acclorite.book_story.domain.browse
import androidx.compose.runtime.Immutable
@Immutable
enum class BrowseFilesStructure {
ALL_FILES, DIRECTORIES
}
fun String.toBrowseFilesStructure(): BrowseFilesStructure {
return BrowseFilesStructure.valueOf(this)
}

View file

@ -3,11 +3,14 @@ package ua.acclorite.book_story.domain.browse
enum class BrowseSortOrder { enum class BrowseSortOrder {
NAME, NAME,
FILE_FORMAT, FILE_FORMAT,
FILE_TYPE,
LAST_MODIFIED, LAST_MODIFIED,
FILE_SIZE, FILE_SIZE,
} }
fun String.toBrowseSortOrder(): BrowseSortOrder { fun String.toBrowseSortOrder(): BrowseSortOrder {
return BrowseSortOrder.valueOf(this) return try {
BrowseSortOrder.valueOf(this)
} catch (_: IllegalArgumentException) {
BrowseSortOrder.LAST_MODIFIED
}
} }

View file

@ -1,11 +0,0 @@
package ua.acclorite.book_story.domain.browse
import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.domain.ui.UIText
import java.io.File
@Immutable
data class FileWithTitle(
val title: UIText,
val file: File
)

View file

@ -1,14 +1,12 @@
package ua.acclorite.book_story.domain.browse package ua.acclorite.book_story.domain.browse
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.domain.util.Selected
import java.io.File
@Immutable @Immutable
data class SelectableFile( data class SelectableFile(
val fileOrDirectory: File, val name: String,
val parentDirectory: File, val path: String,
val isDirectory: Boolean, val size: Long,
val isFavorite: Boolean, val lastModified: Long,
val isSelected: Selected val selected: Boolean
) )

View file

@ -1,6 +0,0 @@
package ua.acclorite.book_story.domain.repository
interface FavoriteDirectoryRepository {
suspend fun updateFavoriteDirectory(path: String)
}

View file

@ -1,13 +0,0 @@
package ua.acclorite.book_story.domain.use_case.favorite_directory
import ua.acclorite.book_story.domain.repository.FavoriteDirectoryRepository
import javax.inject.Inject
class UpdateFavoriteDirectory @Inject constructor(
private val repository: FavoriteDirectoryRepository
) {
suspend fun execute(path: String) {
return repository.updateFavoriteDirectory(path)
}
}

View file

@ -8,10 +8,8 @@ import ua.acclorite.book_story.ui.browse.BrowseEvent
fun BrowseBackHandler( fun BrowseBackHandler(
hasSelectedItems: Boolean, hasSelectedItems: Boolean,
showSearch: Boolean, showSearch: Boolean,
inNestedDirectory: Boolean,
searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit, searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit,
clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit, clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit,
goBackDirectory: (BrowseEvent.OnGoBackDirectory) -> Unit,
navigateToLibrary: () -> Unit navigateToLibrary: () -> Unit
) { ) {
BackHandler { BackHandler {
@ -25,11 +23,6 @@ fun BrowseBackHandler(
return@BackHandler return@BackHandler
} }
if (inNestedDirectory) {
goBackDirectory(BrowseEvent.OnGoBackDirectory)
return@BackHandler
}
navigateToLibrary() navigateToLibrary()
} }
} }

View file

@ -8,14 +8,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.browse.BrowseLayout import ua.acclorite.book_story.domain.browse.BrowseLayout
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.domain.library.book.SelectableNullableBook import ua.acclorite.book_story.domain.library.book.SelectableNullableBook
import ua.acclorite.book_story.domain.util.BottomSheet import ua.acclorite.book_story.domain.util.BottomSheet
import ua.acclorite.book_story.domain.util.Dialog import ua.acclorite.book_story.domain.util.Dialog
import ua.acclorite.book_story.ui.browse.BrowseEvent import ua.acclorite.book_story.ui.browse.BrowseEvent
import java.io.File
@OptIn(ExperimentalMaterialApi::class, ExperimentalPermissionsApi::class) @OptIn(ExperimentalMaterialApi::class, ExperimentalPermissionsApi::class)
@Composable @Composable
@ -30,14 +28,11 @@ fun BrowseContent(
listState: LazyListState, listState: LazyListState,
gridState: LazyGridState, gridState: LazyGridState,
layout: BrowseLayout, layout: BrowseLayout,
filesStructure: BrowseFilesStructure,
gridSize: Int, gridSize: Int,
autoGridSize: Boolean, autoGridSize: Boolean,
includedFilterItems: List<String>, includedFilterItems: List<String>,
canScrollBackList: Boolean, canScrollBackList: Boolean,
canScrollBackGrid: Boolean, canScrollBackGrid: Boolean,
selectedDirectory: File,
inNestedDirectory: Boolean,
hasSelectedItems: Boolean, hasSelectedItems: Boolean,
selectedItemsCount: Int, selectedItemsCount: Int,
isRefreshing: Boolean, isRefreshing: Boolean,
@ -47,19 +42,15 @@ fun BrowseContent(
filesEmpty: Boolean, filesEmpty: Boolean,
showSearch: Boolean, showSearch: Boolean,
searchQuery: String, searchQuery: String,
hasSearched: Boolean,
focusRequester: FocusRequester, focusRequester: FocusRequester,
searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit, searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit,
searchQueryChange: (BrowseEvent.OnSearchQueryChange) -> Unit, searchQueryChange: (BrowseEvent.OnSearchQueryChange) -> Unit,
search: (BrowseEvent.OnSearch) -> Unit, search: (BrowseEvent.OnSearch) -> Unit,
requestFocus: (BrowseEvent.OnRequestFocus) -> Unit, requestFocus: (BrowseEvent.OnRequestFocus) -> Unit,
clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit, clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit,
goBackDirectory: (BrowseEvent.OnGoBackDirectory) -> Unit,
selectFiles: (BrowseEvent.OnSelectFiles) -> Unit, selectFiles: (BrowseEvent.OnSelectFiles) -> Unit,
selectFile: (BrowseEvent.OnSelectFile) -> Unit, selectFile: (BrowseEvent.OnSelectFile) -> Unit,
permissionCheck: (BrowseEvent.OnPermissionCheck) -> Unit, permissionCheck: (BrowseEvent.OnPermissionCheck) -> Unit,
updateFavoriteDirectory: (BrowseEvent.OnUpdateFavoriteDirectory) -> Unit,
changeDirectory: (BrowseEvent.OnChangeDirectory) -> Unit,
dismissBottomSheet: (BrowseEvent.OnDismissBottomSheet) -> Unit, dismissBottomSheet: (BrowseEvent.OnDismissBottomSheet) -> Unit,
showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit, showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit,
actionPermissionDialog: (BrowseEvent.OnActionPermissionDialog) -> Unit, actionPermissionDialog: (BrowseEvent.OnActionPermissionDialog) -> Unit,
@ -95,28 +86,23 @@ fun BrowseContent(
listState = listState, listState = listState,
gridState = gridState, gridState = gridState,
layout = layout, layout = layout,
filesStructure = filesStructure,
gridSize = gridSize, gridSize = gridSize,
autoGridSize = autoGridSize, autoGridSize = autoGridSize,
includedFilterItems = includedFilterItems, includedFilterItems = includedFilterItems,
canScrollBackList = canScrollBackList, canScrollBackList = canScrollBackList,
canScrollBackGrid = canScrollBackGrid, canScrollBackGrid = canScrollBackGrid,
selectedDirectory = selectedDirectory,
inNestedDirectory = inNestedDirectory,
hasSelectedItems = hasSelectedItems, hasSelectedItems = hasSelectedItems,
selectedItemsCount = selectedItemsCount, selectedItemsCount = selectedItemsCount,
isRefreshing = isRefreshing, isRefreshing = isRefreshing,
dialogHidden = dialogHidden, dialogHidden = dialogHidden,
showSearch = showSearch, showSearch = showSearch,
searchQuery = searchQuery, searchQuery = searchQuery,
hasSearched = hasSearched,
focusRequester = focusRequester, focusRequester = focusRequester,
searchVisibility = searchVisibility, searchVisibility = searchVisibility,
searchQueryChange = searchQueryChange, searchQueryChange = searchQueryChange,
search = search, search = search,
requestFocus = requestFocus, requestFocus = requestFocus,
clearSelectedFiles = clearSelectedFiles, clearSelectedFiles = clearSelectedFiles,
goBackDirectory = goBackDirectory,
selectFiles = selectFiles, selectFiles = selectFiles,
storagePermissionState = storagePermissionState, storagePermissionState = storagePermissionState,
isLoading = isLoading, isLoading = isLoading,
@ -124,8 +110,6 @@ fun BrowseContent(
filesEmpty = filesEmpty, filesEmpty = filesEmpty,
permissionCheck = permissionCheck, permissionCheck = permissionCheck,
selectFile = selectFile, selectFile = selectFile,
updateFavoriteDirectory = updateFavoriteDirectory,
changeDirectory = changeDirectory,
showFilterBottomSheet = showFilterBottomSheet, showFilterBottomSheet = showFilterBottomSheet,
showAddDialog = showAddDialog, showAddDialog = showAddDialog,
navigateToHelp = navigateToHelp navigateToHelp = navigateToHelp
@ -134,10 +118,8 @@ fun BrowseContent(
BrowseBackHandler( BrowseBackHandler(
hasSelectedItems = hasSelectedItems, hasSelectedItems = hasSelectedItems,
showSearch = showSearch, showSearch = showSearch,
inNestedDirectory = inNestedDirectory,
searchVisibility = searchVisibility, searchVisibility = searchVisibility,
clearSelectedFiles = clearSelectedFiles, clearSelectedFiles = clearSelectedFiles,
goBackDirectory = goBackDirectory,
navigateToLibrary = navigateToLibrary navigateToLibrary = navigateToLibrary
) )
} }

View file

@ -1,126 +0,0 @@
package ua.acclorite.book_story.presentation.browse
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material.icons.filled.Folder
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.presentation.core.components.common.CircularCheckbox
import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.ui.theme.DefaultTransition
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@Composable
fun BrowseGridDirectoryItem(
file: SelectableFile,
hasSelectedFiles: Boolean,
onFavoriteClick: () -> Unit
) {
val lastModified = rememberSaveable {
SimpleDateFormat("dd MMM yyyy", Locale.getDefault())
.format(Date(file.fileOrDirectory.lastModified()))
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(
modifier = Modifier
.border(
1.dp,
if (file.isSelected) MaterialTheme.colorScheme.outline
else MaterialTheme.colorScheme.outlineVariant,
RoundedCornerShape(10.dp)
)
.fillMaxWidth()
.aspectRatio(1f),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Folder,
contentDescription = stringResource(id = R.string.directory_icon_content_desc),
modifier = Modifier
.fillMaxWidth(0.3f)
.aspectRatio(1f),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
DefaultTransition(
visible = hasSelectedFiles,
modifier = Modifier
.align(Alignment.TopStart)
.padding(12.dp)
) {
CircularCheckbox(
selected = file.isSelected,
containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp
)
}
DefaultTransition(
visible = !hasSelectedFiles,
modifier = Modifier
.align(Alignment.TopStart)
.padding(12.dp)
) {
Icon(
imageVector = if (file.isFavorite) Icons.Default.Favorite
else Icons.Default.FavoriteBorder,
contentDescription = stringResource(
id = R.string.favorite_directory_content_desc
),
modifier = Modifier
.size(24.dp)
.noRippleClickable(enabled = !hasSelectedFiles) {
onFavoriteClick()
},
tint = if (file.isFavorite) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onSurfaceVariant.copy(0.8f)
)
}
}
Spacer(modifier = Modifier.height(8.dp))
Text(
file.fileOrDirectory.name,
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.bodyLarge,
maxLines = 2,
textAlign = TextAlign.Center,
lineHeight = 18.sp,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(2.dp))
Text(
lastModified,
color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.bodySmall,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}

View file

@ -32,13 +32,13 @@ import java.util.Date
import java.util.Locale import java.util.Locale
@Composable @Composable
fun BrowseGridFileItem(file: SelectableFile, hasSelectedFiles: Boolean) { fun BrowseGridFileItem(file: SelectableFile, hasSelectedItems: Boolean) {
val lastModified = rememberSaveable { val lastModified = rememberSaveable {
SimpleDateFormat("dd MMM yyyy", Locale.getDefault()) SimpleDateFormat("dd MMM yyyy", Locale.getDefault())
.format(Date(file.fileOrDirectory.lastModified())) .format(Date(file.lastModified))
} }
val sizeBytes = rememberSaveable { file.fileOrDirectory.length() } val sizeBytes = rememberSaveable { file.size }
val fileSizeKB = rememberSaveable { val fileSizeKB = rememberSaveable {
if (sizeBytes > 0) sizeBytes.toDouble() / 1024.0 else 0.0 if (sizeBytes > 0) sizeBytes.toDouble() / 1024.0 else 0.0
} }
@ -56,7 +56,7 @@ fun BrowseGridFileItem(file: SelectableFile, hasSelectedFiles: Boolean) {
modifier = Modifier modifier = Modifier
.border( .border(
1.dp, 1.dp,
if (file.isSelected) MaterialTheme.colorScheme.outline if (file.selected) MaterialTheme.colorScheme.outline
else MaterialTheme.colorScheme.outlineVariant, else MaterialTheme.colorScheme.outlineVariant,
RoundedCornerShape(10.dp) RoundedCornerShape(10.dp)
) )
@ -74,11 +74,11 @@ fun BrowseGridFileItem(file: SelectableFile, hasSelectedFiles: Boolean) {
) )
DefaultTransition( DefaultTransition(
visible = hasSelectedFiles, visible = hasSelectedItems,
modifier = Modifier.align(Alignment.TopStart) modifier = Modifier.align(Alignment.TopStart)
) { ) {
CircularCheckbox( CircularCheckbox(
selected = file.isSelected, selected = file.selected,
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp, size = 18.dp,
modifier = Modifier.padding(12.dp) modifier = Modifier.padding(12.dp)
@ -89,7 +89,7 @@ fun BrowseGridFileItem(file: SelectableFile, hasSelectedFiles: Boolean) {
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Text( Text(
file.fileOrDirectory.name, file.name,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
maxLines = 2, maxLines = 2,

View file

@ -20,9 +20,8 @@ import ua.acclorite.book_story.domain.browse.SelectableFile
fun BrowseGridItem( fun BrowseGridItem(
modifier: Modifier, modifier: Modifier,
file: SelectableFile, file: SelectableFile,
hasSelectedFiles: Boolean, hasSelectedItems: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
onFavoriteClick: () -> Unit,
onLongClick: () -> Unit onLongClick: () -> Unit
) { ) {
Column( Column(
@ -31,7 +30,7 @@ fun BrowseGridItem(
.padding(3.dp) .padding(3.dp)
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(12.dp))
.background( .background(
if (file.isSelected) MaterialTheme.colorScheme.secondaryContainer if (file.selected) MaterialTheme.colorScheme.secondaryContainer
else Color.Transparent, else Color.Transparent,
RoundedCornerShape(12.dp) RoundedCornerShape(12.dp)
) )
@ -41,21 +40,9 @@ fun BrowseGridItem(
) )
.padding(5.dp) .padding(5.dp)
) { ) {
when { BrowseGridFileItem(
!file.isDirectory -> { file = file,
BrowseGridFileItem( hasSelectedItems = hasSelectedItems
file = file, )
hasSelectedFiles = hasSelectedFiles
)
}
file.isDirectory -> {
BrowseGridDirectoryItem(
file = file,
hasSelectedFiles = hasSelectedFiles,
onFavoriteClick = onFavoriteClick
)
}
}
} }
} }

View file

@ -23,9 +23,8 @@ fun BrowseGridLayout(
autoGridSize: Boolean, autoGridSize: Boolean,
gridState: LazyGridState, gridState: LazyGridState,
files: List<SelectableFile>, files: List<SelectableFile>,
hasSelectedFiles: Boolean, hasSelectedItems: Boolean,
onLongItemClick: (SelectableFile) -> Unit, onLongItemClick: (SelectableFile) -> Unit,
onFavoriteItemClick: (SelectableFile) -> Unit,
onItemClick: (SelectableFile) -> Unit, onItemClick: (SelectableFile) -> Unit,
) { ) {
LazyVerticalGridWithScrollbar( LazyVerticalGridWithScrollbar(
@ -43,19 +42,16 @@ fun BrowseGridLayout(
items( items(
files, files,
key = { it.fileOrDirectory.path } key = { it.path }
) { selectableFile -> ) { selectableFile ->
BrowseItem( BrowseItem(
file = selectableFile, file = selectableFile,
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
layout = BrowseLayout.GRID, layout = BrowseLayout.GRID,
hasSelectedFiles = hasSelectedFiles, hasSelectedItems = hasSelectedItems,
onLongClick = { onLongClick = {
onLongItemClick(selectableFile) onLongItemClick(selectableFile)
}, },
onFavoriteClick = {
onFavoriteItemClick(selectableFile)
},
onClick = { onClick = {
onItemClick(selectableFile) onItemClick(selectableFile)
} }

View file

@ -9,10 +9,9 @@ import ua.acclorite.book_story.domain.browse.SelectableFile
fun BrowseItem( fun BrowseItem(
layout: BrowseLayout, layout: BrowseLayout,
file: SelectableFile, file: SelectableFile,
hasSelectedFiles: Boolean, hasSelectedItems: Boolean,
modifier: Modifier, modifier: Modifier,
onClick: () -> Unit, onClick: () -> Unit,
onFavoriteClick: () -> Unit,
onLongClick: () -> Unit onLongClick: () -> Unit
) { ) {
when (layout) { when (layout) {
@ -20,9 +19,8 @@ fun BrowseItem(
BrowseListItem( BrowseListItem(
modifier = modifier, modifier = modifier,
file = file, file = file,
hasSelectedFiles = hasSelectedFiles, hasSelectedItems = hasSelectedItems,
onClick = onClick, onClick = onClick,
onFavoriteClick = onFavoriteClick,
onLongClick = onLongClick onLongClick = onLongClick
) )
} }
@ -31,9 +29,8 @@ fun BrowseItem(
BrowseGridItem( BrowseGridItem(
modifier = modifier, modifier = modifier,
file = file, file = file,
hasSelectedFiles = hasSelectedFiles, hasSelectedItems = hasSelectedItems,
onClick = onClick, onClick = onClick,
onFavoriteClick = onFavoriteClick,
onLongClick = onLongClick onLongClick = onLongClick
) )
} }

View file

@ -9,24 +9,22 @@ import ua.acclorite.book_story.domain.browse.SelectableFile
@Composable @Composable
fun BrowseLayout( fun BrowseLayout(
files: List<SelectableFile>, files: List<SelectableFile>,
hasSelectedFiles: Boolean, hasSelectedItems: Boolean,
layout: BrowseLayout, layout: BrowseLayout,
gridSize: Int, gridSize: Int,
autoGridSize: Boolean, autoGridSize: Boolean,
listState: LazyListState, listState: LazyListState,
gridState: LazyGridState, gridState: LazyGridState,
onLongItemClick: (SelectableFile) -> Unit, onLongItemClick: (SelectableFile) -> Unit,
onFavoriteItemClick: (SelectableFile) -> Unit,
onItemClick: (SelectableFile) -> Unit onItemClick: (SelectableFile) -> Unit
) { ) {
when (layout) { when (layout) {
BrowseLayout.LIST -> { BrowseLayout.LIST -> {
BrowseListLayout( BrowseListLayout(
files = files, files = files,
hasSelectedFiles = hasSelectedFiles, hasSelectedItems = hasSelectedItems,
listState = listState, listState = listState,
onLongItemClick = onLongItemClick, onLongItemClick = onLongItemClick,
onFavoriteItemClick = onFavoriteItemClick,
onItemClick = onItemClick onItemClick = onItemClick
) )
} }
@ -36,10 +34,9 @@ fun BrowseLayout(
gridSize = gridSize, gridSize = gridSize,
autoGridSize = autoGridSize, autoGridSize = autoGridSize,
files = files, files = files,
hasSelectedFiles = hasSelectedFiles, hasSelectedItems = hasSelectedItems,
gridState = gridState, gridState = gridState,
onLongItemClick = onLongItemClick, onLongItemClick = onLongItemClick,
onFavoriteItemClick = onFavoriteItemClick,
onItemClick = onItemClick onItemClick = onItemClick
) )
} }

View file

@ -1,73 +0,0 @@
package ua.acclorite.book_story.presentation.browse
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Folder
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.SelectableFile
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@Composable
fun RowScope.BrowseListDirectoryItem(file: SelectableFile) {
val lastModified = rememberSaveable {
SimpleDateFormat("dd MMM yyyy", Locale.getDefault())
.format(Date(file.fileOrDirectory.lastModified()))
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1f)
) {
Icon(
imageVector = Icons.Default.Folder,
contentDescription = stringResource(id = R.string.directory_icon_content_desc),
modifier = Modifier
.padding(14.dp)
.size(22.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.width(12.dp))
Column(verticalArrangement = Arrangement.Center) {
Text(
file.fileOrDirectory.name,
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.bodyLarge,
maxLines = 2,
lineHeight = 18.sp,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(2.dp))
Text(
lastModified,
color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.bodySmall,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.fillMaxWidth()
)
}
}
}

View file

@ -36,10 +36,10 @@ import java.util.Locale
fun RowScope.BrowseListFileItem(file: SelectableFile) { fun RowScope.BrowseListFileItem(file: SelectableFile) {
val lastModified = rememberSaveable { val lastModified = rememberSaveable {
SimpleDateFormat("HH:mm dd MMM yyyy", Locale.getDefault()) SimpleDateFormat("HH:mm dd MMM yyyy", Locale.getDefault())
.format(Date(file.fileOrDirectory.lastModified())) .format(Date(file.lastModified))
} }
val sizeBytes = rememberSaveable { file.fileOrDirectory.length() } val sizeBytes = rememberSaveable { file.size }
val fileSizeKB = rememberSaveable { val fileSizeKB = rememberSaveable {
if (sizeBytes > 0) sizeBytes.toDouble() / 1024.0 else 0.0 if (sizeBytes > 0) sizeBytes.toDouble() / 1024.0 else 0.0
} }
@ -60,7 +60,7 @@ fun RowScope.BrowseListFileItem(file: SelectableFile) {
modifier = Modifier modifier = Modifier
.border( .border(
1.dp, 1.dp,
if (file.isSelected) MaterialTheme.colorScheme.outline if (file.selected) MaterialTheme.colorScheme.outline
else MaterialTheme.colorScheme.outlineVariant, else MaterialTheme.colorScheme.outlineVariant,
RoundedCornerShape(6.dp) RoundedCornerShape(6.dp)
) )
@ -78,7 +78,7 @@ fun RowScope.BrowseListFileItem(file: SelectableFile) {
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
Column(verticalArrangement = Arrangement.Center) { Column(verticalArrangement = Arrangement.Center) {
Text( Text(
file.fileOrDirectory.name, file.name,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
maxLines = 2, maxLines = 2,

View file

@ -3,30 +3,21 @@ package ua.acclorite.book_story.presentation.browse
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.presentation.core.components.common.CircularCheckbox import ua.acclorite.book_story.presentation.core.components.common.CircularCheckbox
import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.ui.theme.FadeTransitionPreservingSpace import ua.acclorite.book_story.ui.theme.FadeTransitionPreservingSpace
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@ -34,9 +25,8 @@ import ua.acclorite.book_story.ui.theme.FadeTransitionPreservingSpace
fun BrowseListItem( fun BrowseListItem(
modifier: Modifier, modifier: Modifier,
file: SelectableFile, file: SelectableFile,
hasSelectedFiles: Boolean, hasSelectedItems: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
onFavoriteClick: () -> Unit,
onLongClick: () -> Unit onLongClick: () -> Unit
) { ) {
Row( Row(
@ -46,7 +36,7 @@ fun BrowseListItem(
.padding(horizontal = 8.dp, vertical = 3.dp) .padding(horizontal = 8.dp, vertical = 3.dp)
.clip(RoundedCornerShape(10.dp)) .clip(RoundedCornerShape(10.dp))
.background( .background(
if (file.isSelected) MaterialTheme.colorScheme.secondaryContainer if (file.selected) MaterialTheme.colorScheme.secondaryContainer
else Color.Transparent, else Color.Transparent,
RoundedCornerShape(10.dp) RoundedCornerShape(10.dp)
) )
@ -60,59 +50,19 @@ fun BrowseListItem(
) )
.padding(horizontal = 8.dp, vertical = 7.dp) .padding(horizontal = 8.dp, vertical = 7.dp)
) { ) {
when { BrowseListFileItem(file = file)
!file.isDirectory -> {
BrowseListFileItem(file = file)
FadeTransitionPreservingSpace(visible = hasSelectedFiles) { FadeTransitionPreservingSpace(visible = hasSelectedItems) {
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
CircularCheckbox( CircularCheckbox(
selected = file.isSelected, selected = file.selected,
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp size = 18.dp
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
}
}
}
file.isDirectory -> {
BrowseListDirectoryItem(file = file)
Row(verticalAlignment = Alignment.CenterVertically) {
Spacer(modifier = Modifier.width(16.dp))
Box(contentAlignment = Alignment.Center) {
FadeTransitionPreservingSpace(hasSelectedFiles) {
CircularCheckbox(
selected = file.isSelected,
containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp
)
}
FadeTransitionPreservingSpace(!hasSelectedFiles) {
Icon(
imageVector = if (file.isFavorite) Icons.Default.Favorite
else Icons.Default.FavoriteBorder,
contentDescription = stringResource(
id = R.string.favorite_directory_content_desc
),
modifier = Modifier
.size(24.dp)
.noRippleClickable(enabled = !hasSelectedFiles) {
onFavoriteClick()
},
tint = if (file.isFavorite) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onSurfaceVariant.copy(0.8f)
)
}
}
Spacer(modifier = Modifier.width(8.dp))
}
} }
} }
} }

View file

@ -17,10 +17,9 @@ import ua.acclorite.book_story.presentation.core.constants.providePrimaryScrollb
@Composable @Composable
fun BrowseListLayout( fun BrowseListLayout(
files: List<SelectableFile>, files: List<SelectableFile>,
hasSelectedFiles: Boolean, hasSelectedItems: Boolean,
listState: LazyListState, listState: LazyListState,
onLongItemClick: (SelectableFile) -> Unit, onLongItemClick: (SelectableFile) -> Unit,
onFavoriteItemClick: (SelectableFile) -> Unit,
onItemClick: (SelectableFile) -> Unit, onItemClick: (SelectableFile) -> Unit,
) { ) {
LazyColumnWithScrollbar( LazyColumnWithScrollbar(
@ -34,19 +33,16 @@ fun BrowseListLayout(
items( items(
files, files,
key = { it.fileOrDirectory.path } key = { it.path }
) { selectableFile -> ) { selectableFile ->
BrowseItem( BrowseItem(
file = selectableFile, file = selectableFile,
layout = BrowseLayout.LIST, layout = BrowseLayout.LIST,
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
hasSelectedFiles = hasSelectedFiles, hasSelectedItems = hasSelectedItems,
onLongClick = { onLongClick = {
onLongItemClick(selectableFile) onLongItemClick(selectableFile)
}, },
onFavoriteClick = {
onFavoriteItemClick(selectableFile)
},
onClick = { onClick = {
onItemClick(selectableFile) onItemClick(selectableFile)
} }

View file

@ -16,14 +16,12 @@ import androidx.compose.ui.focus.FocusRequester
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.browse.BrowseLayout import ua.acclorite.book_story.domain.browse.BrowseLayout
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.presentation.core.util.LocalActivity import ua.acclorite.book_story.presentation.core.util.LocalActivity
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.ui.browse.BrowseEvent import ua.acclorite.book_story.ui.browse.BrowseEvent
import ua.acclorite.book_story.ui.theme.DefaultTransition import ua.acclorite.book_story.ui.theme.DefaultTransition
import java.io.File
@OptIn(ExperimentalMaterialApi::class, ExperimentalPermissionsApi::class) @OptIn(ExperimentalMaterialApi::class, ExperimentalPermissionsApi::class)
@Composable @Composable
@ -34,14 +32,11 @@ fun BrowseScaffold(
listState: LazyListState, listState: LazyListState,
gridState: LazyGridState, gridState: LazyGridState,
layout: BrowseLayout, layout: BrowseLayout,
filesStructure: BrowseFilesStructure,
gridSize: Int, gridSize: Int,
autoGridSize: Boolean, autoGridSize: Boolean,
includedFilterItems: List<String>, includedFilterItems: List<String>,
canScrollBackList: Boolean, canScrollBackList: Boolean,
canScrollBackGrid: Boolean, canScrollBackGrid: Boolean,
selectedDirectory: File,
inNestedDirectory: Boolean,
hasSelectedItems: Boolean, hasSelectedItems: Boolean,
selectedItemsCount: Int, selectedItemsCount: Int,
isRefreshing: Boolean, isRefreshing: Boolean,
@ -51,19 +46,15 @@ fun BrowseScaffold(
filesEmpty: Boolean, filesEmpty: Boolean,
showSearch: Boolean, showSearch: Boolean,
searchQuery: String, searchQuery: String,
hasSearched: Boolean,
focusRequester: FocusRequester, focusRequester: FocusRequester,
searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit, searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit,
searchQueryChange: (BrowseEvent.OnSearchQueryChange) -> Unit, searchQueryChange: (BrowseEvent.OnSearchQueryChange) -> Unit,
search: (BrowseEvent.OnSearch) -> Unit, search: (BrowseEvent.OnSearch) -> Unit,
requestFocus: (BrowseEvent.OnRequestFocus) -> Unit, requestFocus: (BrowseEvent.OnRequestFocus) -> Unit,
goBackDirectory: (BrowseEvent.OnGoBackDirectory) -> Unit,
clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit, clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit,
selectFiles: (BrowseEvent.OnSelectFiles) -> Unit, selectFiles: (BrowseEvent.OnSelectFiles) -> Unit,
selectFile: (BrowseEvent.OnSelectFile) -> Unit, selectFile: (BrowseEvent.OnSelectFile) -> Unit,
permissionCheck: (BrowseEvent.OnPermissionCheck) -> Unit, permissionCheck: (BrowseEvent.OnPermissionCheck) -> Unit,
updateFavoriteDirectory: (BrowseEvent.OnUpdateFavoriteDirectory) -> Unit,
changeDirectory: (BrowseEvent.OnChangeDirectory) -> Unit,
showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit, showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit,
showAddDialog: (BrowseEvent.OnShowAddDialog) -> Unit, showAddDialog: (BrowseEvent.OnShowAddDialog) -> Unit,
navigateToHelp: () -> Unit, navigateToHelp: () -> Unit,
@ -79,27 +70,20 @@ fun BrowseScaffold(
BrowseTopBar( BrowseTopBar(
files = files, files = files,
layout = layout, layout = layout,
filesStructure = filesStructure,
includedFilterItems = includedFilterItems, includedFilterItems = includedFilterItems,
canScrollBackList = canScrollBackList, canScrollBackList = canScrollBackList,
canScrollBackGrid = canScrollBackGrid, canScrollBackGrid = canScrollBackGrid,
selectedDirectory = selectedDirectory,
inNestedDirectory = inNestedDirectory,
hasSelectedItems = hasSelectedItems, hasSelectedItems = hasSelectedItems,
selectedItemsCount = selectedItemsCount, selectedItemsCount = selectedItemsCount,
showSearch = showSearch, showSearch = showSearch,
searchQuery = searchQuery, searchQuery = searchQuery,
hasSearched = hasSearched,
isError = isError,
focusRequester = focusRequester, focusRequester = focusRequester,
searchVisibility = searchVisibility, searchVisibility = searchVisibility,
searchQueryChange = searchQueryChange, searchQueryChange = searchQueryChange,
search = search, search = search,
requestFocus = requestFocus, requestFocus = requestFocus,
goBackDirectory = goBackDirectory,
clearSelectedFiles = clearSelectedFiles, clearSelectedFiles = clearSelectedFiles,
selectFiles = selectFiles, selectFiles = selectFiles,
changeDirectory = changeDirectory,
showFilterBottomSheet = showFilterBottomSheet, showFilterBottomSheet = showFilterBottomSheet,
showAddDialog = showAddDialog showAddDialog = showAddDialog
) )
@ -114,66 +98,24 @@ fun BrowseScaffold(
BrowseLayout( BrowseLayout(
files = files, files = files,
layout = layout, layout = layout,
hasSelectedFiles = files.any { it.isSelected }, hasSelectedItems = hasSelectedItems,
gridSize = gridSize, gridSize = gridSize,
autoGridSize = autoGridSize, autoGridSize = autoGridSize,
listState = listState, listState = listState,
gridState = gridState, gridState = gridState,
onLongItemClick = { file -> onLongItemClick = { file ->
when (file.isDirectory) { context.getString(
false -> { R.string.file_path_query,
context.getString( file.path
R.string.file_path_query, ).showToast(context = context)
file.fileOrDirectory.path
).showToast(context = context)
}
true -> {
selectFile(
BrowseEvent.OnSelectFile(
includedFileFormats = includedFilterItems,
file = file
)
)
}
}
},
onFavoriteItemClick = { file ->
updateFavoriteDirectory(
BrowseEvent.OnUpdateFavoriteDirectory(
file.fileOrDirectory.path
)
)
}, },
onItemClick = { file -> onItemClick = { file ->
when (file.isDirectory) { selectFile(
false -> { BrowseEvent.OnSelectFile(
selectFile( includedFileFormats = includedFilterItems,
BrowseEvent.OnSelectFile( file = file
includedFileFormats = includedFilterItems, )
file = file )
)
)
}
true -> {
if (!hasSelectedItems) {
changeDirectory(
BrowseEvent.OnChangeDirectory(
file.fileOrDirectory,
savePreviousDirectory = true
)
)
} else {
selectFile(
BrowseEvent.OnSelectFile(
includedFileFormats = includedFilterItems,
file = file
)
)
}
}
}
} }
) )
} }

View file

@ -13,9 +13,7 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
@ -24,7 +22,6 @@ import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.browse.BrowseLayout import ua.acclorite.book_story.domain.browse.BrowseLayout
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.presentation.core.components.common.IconButton import ua.acclorite.book_story.presentation.core.components.common.IconButton
@ -33,40 +30,29 @@ import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBar
import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBarData import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBarData
import ua.acclorite.book_story.presentation.navigator.NavigatorIconButton import ua.acclorite.book_story.presentation.navigator.NavigatorIconButton
import ua.acclorite.book_story.ui.browse.BrowseEvent import ua.acclorite.book_story.ui.browse.BrowseEvent
import java.io.File
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun BrowseTopBar( fun BrowseTopBar(
files: List<SelectableFile>, files: List<SelectableFile>,
layout: BrowseLayout, layout: BrowseLayout,
filesStructure: BrowseFilesStructure,
includedFilterItems: List<String>, includedFilterItems: List<String>,
canScrollBackList: Boolean, canScrollBackList: Boolean,
canScrollBackGrid: Boolean, canScrollBackGrid: Boolean,
selectedDirectory: File,
inNestedDirectory: Boolean,
hasSelectedItems: Boolean, hasSelectedItems: Boolean,
selectedItemsCount: Int, selectedItemsCount: Int,
showSearch: Boolean, showSearch: Boolean,
searchQuery: String, searchQuery: String,
hasSearched: Boolean,
isError: Boolean,
focusRequester: FocusRequester, focusRequester: FocusRequester,
searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit, searchVisibility: (BrowseEvent.OnSearchVisibility) -> Unit,
searchQueryChange: (BrowseEvent.OnSearchQueryChange) -> Unit, searchQueryChange: (BrowseEvent.OnSearchQueryChange) -> Unit,
search: (BrowseEvent.OnSearch) -> Unit, search: (BrowseEvent.OnSearch) -> Unit,
requestFocus: (BrowseEvent.OnRequestFocus) -> Unit, requestFocus: (BrowseEvent.OnRequestFocus) -> Unit,
goBackDirectory: (BrowseEvent.OnGoBackDirectory) -> Unit,
clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit, clearSelectedFiles: (BrowseEvent.OnClearSelectedFiles) -> Unit,
selectFiles: (BrowseEvent.OnSelectFiles) -> Unit, selectFiles: (BrowseEvent.OnSelectFiles) -> Unit,
changeDirectory: (BrowseEvent.OnChangeDirectory) -> Unit,
showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit, showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit,
showAddDialog: (BrowseEvent.OnShowAddDialog) -> Unit showAddDialog: (BrowseEvent.OnShowAddDialog) -> Unit
) { ) {
val selectedDirectoryName = remember {
mutableStateOf(selectedDirectory.name)
}
val isScrolled = remember(layout, canScrollBackList, canScrollBackGrid) { val isScrolled = remember(layout, canScrollBackList, canScrollBackGrid) {
derivedStateOf { derivedStateOf {
when (layout) { when (layout) {
@ -82,20 +68,13 @@ fun BrowseTopBar(
} else LocalContentColor.current } else LocalContentColor.current
) )
LaunchedEffect(inNestedDirectory, selectedDirectory) {
if (inNestedDirectory) {
selectedDirectoryName.value = selectedDirectory.name
}
}
TopAppBar( TopAppBar(
scrollBehavior = null, scrollBehavior = null,
isTopBarScrolled = isScrolled.value || hasSelectedItems, isTopBarScrolled = isScrolled.value || hasSelectedItems,
shownTopBar = when { shownTopBar = when {
hasSelectedItems -> 3 hasSelectedItems -> 2
showSearch -> 2 showSearch -> 1
inNestedDirectory -> 1
else -> 0 else -> 0
}, },
topBars = listOf( topBars = listOf(
@ -131,45 +110,6 @@ fun BrowseTopBar(
TopAppBarData( TopAppBarData(
contentID = 1, contentID = 1,
contentNavigationIcon = {
IconButton(
icon = Icons.AutoMirrored.Default.ArrowBack,
contentDescription = R.string.go_back_content_desc,
disableOnClick = false,
enabled = inNestedDirectory
) {
goBackDirectory(BrowseEvent.OnGoBackDirectory)
}
},
contentTitle = {
Text(
selectedDirectoryName.value,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
contentActions = {
IconButton(
icon = Icons.Default.Search,
contentDescription = R.string.search_content_desc,
disableOnClick = true
) {
searchVisibility(BrowseEvent.OnSearchVisibility(true))
}
IconButton(
icon = Icons.Default.FilterList,
contentDescription = R.string.filter_content_desc,
disableOnClick = false,
color = animatedFilterIconColor.value
) {
showFilterBottomSheet(BrowseEvent.OnShowFilterBottomSheet)
}
NavigatorIconButton()
}
),
TopAppBarData(
contentID = 2,
contentNavigationIcon = { contentNavigationIcon = {
IconButton( IconButton(
icon = Icons.AutoMirrored.Default.ArrowBack, icon = Icons.AutoMirrored.Default.ArrowBack,
@ -201,7 +141,7 @@ fun BrowseTopBar(
), ),
TopAppBarData( TopAppBarData(
contentID = 3, contentID = 2,
contentNavigationIcon = { contentNavigationIcon = {
IconButton( IconButton(
icon = Icons.Default.Clear, icon = Icons.Default.Clear,
@ -243,16 +183,6 @@ fun BrowseTopBar(
} }
} }
) )
), )
customContent = {
BrowseTopBarDirectoryPath(
selectedDirectory = selectedDirectory,
hasSelectedItems = hasSelectedItems,
hasSearched = hasSearched,
isError = isError,
filesStructure = filesStructure,
changeDirectory = changeDirectory
)
}
) )
} }

View file

@ -1,160 +0,0 @@
package ua.acclorite.book_story.presentation.browse
import android.os.Environment
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowRight
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.browse.FileWithTitle
import ua.acclorite.book_story.domain.ui.UIText
import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.ui.browse.BrowseEvent
import java.io.File
@Composable
fun BrowseTopBarDirectoryPath(
selectedDirectory: File,
hasSelectedItems: Boolean,
hasSearched: Boolean,
isError: Boolean,
filesStructure: BrowseFilesStructure,
changeDirectory: (BrowseEvent.OnChangeDirectory) -> Unit
) {
val rootDirectory = Environment.getExternalStorageDirectory()
val directories = remember(selectedDirectory) {
val directories = mutableListOf<FileWithTitle>()
if (selectedDirectory == rootDirectory) {
return@remember listOf(
FileWithTitle(
title = UIText.StringResource(R.string.internal_storage),
file = rootDirectory
)
)
}
directories.add(
FileWithTitle(
title = UIText.StringValue(selectedDirectory.name),
file = selectedDirectory
)
)
var currentDirectory = selectedDirectory.parentFile ?: return@remember emptyList()
while (true) {
if (currentDirectory == rootDirectory) {
break
}
directories.add(
FileWithTitle(
title = UIText.StringValue(currentDirectory.name),
file = currentDirectory
)
)
currentDirectory = currentDirectory.parentFile ?: continue
}
directories.add(
FileWithTitle(
title = UIText.StringResource(R.string.internal_storage),
file = rootDirectory
)
)
directories.reversed()
}
val listState = rememberLazyListState(directories.lastIndex)
LaunchedEffect(directories) {
try {
listState.animateScrollToItem(directories.lastIndex)
} catch (e: Exception) {
e.printStackTrace()
}
}
AnimatedVisibility(
visible = !hasSelectedItems
&& !hasSearched
&& !isError
&& filesStructure == BrowseFilesStructure.DIRECTORIES,
enter = expandVertically(),
exit = shrinkVertically()
) {
LazyRow(
Modifier
.fillMaxWidth()
.padding(bottom = 12.dp),
state = listState,
verticalAlignment = Alignment.CenterVertically
) {
itemsIndexed(
directories,
key = { index, _ -> index }
) { index, directory ->
if (index == 0) {
Spacer(modifier = Modifier.width(16.dp))
}
Text(
text = directory.title.asString(),
color = animateColorAsState(
if (index == directories.lastIndex) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onSurface,
label = ""
).value,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.noRippleClickable(
enabled = selectedDirectory != directory.file
) {
changeDirectory(
BrowseEvent.OnChangeDirectory(
directory = directory.file,
savePreviousDirectory = false
)
)
}
)
if (index < directories.lastIndex) {
Spacer(modifier = Modifier.width(4.dp))
Icon(
imageVector = Icons.AutoMirrored.Default.ArrowRight,
contentDescription = stringResource(id = R.string.path_arrow_icon_content_desc),
modifier = Modifier.size(20.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
Spacer(modifier = Modifier.width(4.dp))
} else {
Spacer(modifier = Modifier.width(16.dp))
}
}
}
}
}

View file

@ -59,11 +59,9 @@ object DataStoreConstants {
val PROGRESS_BAR_FONT_SIZE = intPreferencesKey("progress_bar_font_size") val PROGRESS_BAR_FONT_SIZE = intPreferencesKey("progress_bar_font_size")
// Browse settings // Browse settings
val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure")
val BROWSE_LAYOUT = stringPreferencesKey("browse_layout") val BROWSE_LAYOUT = stringPreferencesKey("browse_layout")
val BROWSE_AUTO_GRID_SIZE = booleanPreferencesKey("browse_auto_grid_size") val BROWSE_AUTO_GRID_SIZE = booleanPreferencesKey("browse_auto_grid_size")
val BROWSE_GRID_SIZE = intPreferencesKey("browse_grid_size") val BROWSE_GRID_SIZE = intPreferencesKey("browse_grid_size")
val BROWSE_PIN_FAVORITE_DIRECTORIES = booleanPreferencesKey("browse_pin_favorite_directories")
val BROWSE_SORT_ORDER = stringPreferencesKey("browse_sort_order") val BROWSE_SORT_ORDER = stringPreferencesKey("browse_sort_order")
val BROWSE_SORT_ORDER_DESCENDING = booleanPreferencesKey("browse_sort_order_descending") val BROWSE_SORT_ORDER_DESCENDING = booleanPreferencesKey("browse_sort_order_descending")
val BROWSE_INCLUDED_FILTER_ITEMS = stringSetPreferencesKey("browse_included_filter_items") val BROWSE_INCLUDED_FILTER_ITEMS = stringSetPreferencesKey("browse_included_filter_items")

View file

@ -10,8 +10,6 @@ import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.settings.browse.general.components.BrowseGridSizeOption import ua.acclorite.book_story.presentation.settings.browse.general.components.BrowseGridSizeOption
import ua.acclorite.book_story.presentation.settings.browse.general.components.BrowseLayoutOption import ua.acclorite.book_story.presentation.settings.browse.general.components.BrowseLayoutOption
import ua.acclorite.book_story.presentation.settings.browse.general.components.FilesStructureOption
import ua.acclorite.book_story.presentation.settings.browse.general.components.PinFavoriteDirectoriesOption
import ua.acclorite.book_story.presentation.settings.components.SettingsSubcategory import ua.acclorite.book_story.presentation.settings.components.SettingsSubcategory
fun LazyListScope.BrowseGeneralSubcategory( fun LazyListScope.BrowseGeneralSubcategory(
@ -26,14 +24,6 @@ fun LazyListScope.BrowseGeneralSubcategory(
showTitle = showTitle, showTitle = showTitle,
showDivider = showDivider showDivider = showDivider
) { ) {
item {
FilesStructureOption()
}
item {
PinFavoriteDirectoriesOption()
}
item { item {
BrowseLayoutOption() BrowseLayoutOption()
} }

View file

@ -1,40 +0,0 @@
package ua.acclorite.book_story.presentation.settings.browse.general.components
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.ui.ButtonItem
import ua.acclorite.book_story.presentation.core.components.settings.SegmentedButtonWithTitle
import ua.acclorite.book_story.ui.main.MainEvent
import ua.acclorite.book_story.ui.main.MainModel
@Composable
fun FilesStructureOption() {
val mainModel = hiltViewModel<MainModel>()
val state = mainModel.state.collectAsStateWithLifecycle()
SegmentedButtonWithTitle(
title = stringResource(id = R.string.browse_files_structure_option),
buttons = BrowseFilesStructure.entries.map {
ButtonItem(
it.toString(),
when (it) {
BrowseFilesStructure.ALL_FILES -> stringResource(id = R.string.files_structure_all)
BrowseFilesStructure.DIRECTORIES -> stringResource(id = R.string.files_structure_directory)
},
MaterialTheme.typography.labelLarge,
it == state.value.browseFilesStructure
)
}
) {
mainModel.onEvent(
MainEvent.OnChangeBrowseFilesStructure(
it.id
)
)
}
}

View file

@ -1,32 +0,0 @@
package ua.acclorite.book_story.presentation.settings.browse.general.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.presentation.core.components.settings.SwitchWithTitle
import ua.acclorite.book_story.ui.main.MainEvent
import ua.acclorite.book_story.ui.main.MainModel
import ua.acclorite.book_story.ui.theme.ExpandingTransition
@Composable
fun PinFavoriteDirectoriesOption() {
val mainModel = hiltViewModel<MainModel>()
val state = mainModel.state.collectAsStateWithLifecycle()
ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) {
SwitchWithTitle(
selected = state.value.browsePinFavoriteDirectories,
title = stringResource(id = R.string.browse_pin_favorite_directories_option),
description = stringResource(id = R.string.browse_pin_favorite_directories_option_desc)
) {
mainModel.onEvent(
MainEvent.OnChangeBrowsePinFavoriteDirectories(
!state.value.browsePinFavoriteDirectories
)
)
}
}
}

View file

@ -87,7 +87,6 @@ private fun BrowseSortOptionItem(
when (item) { when (item) {
BrowseSortOrder.NAME -> R.string.browse_sort_order_name BrowseSortOrder.NAME -> R.string.browse_sort_order_name
BrowseSortOrder.FILE_FORMAT -> R.string.browse_sort_order_file_format BrowseSortOrder.FILE_FORMAT -> R.string.browse_sort_order_file_format
BrowseSortOrder.FILE_TYPE -> R.string.browse_sort_order_file_type
BrowseSortOrder.LAST_MODIFIED -> R.string.browse_sort_order_last_modified BrowseSortOrder.LAST_MODIFIED -> R.string.browse_sort_order_last_modified
BrowseSortOrder.FILE_SIZE -> R.string.browse_sort_order_file_size BrowseSortOrder.FILE_SIZE -> R.string.browse_sort_order_file_size
} }

View file

@ -10,7 +10,6 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.domain.library.book.SelectableNullableBook import ua.acclorite.book_story.domain.library.book.SelectableNullableBook
import java.io.File
@Immutable @Immutable
sealed class BrowseEvent { sealed class BrowseEvent {
@ -35,13 +34,6 @@ sealed class BrowseEvent {
data object OnClearSelectedFiles : BrowseEvent() data object OnClearSelectedFiles : BrowseEvent()
data class OnChangeDirectory(
val directory: File,
val savePreviousDirectory: Boolean
) : BrowseEvent()
data object OnGoBackDirectory : BrowseEvent()
data class OnSelectFiles( data class OnSelectFiles(
val includedFileFormats: List<String>, val includedFileFormats: List<String>,
val files: List<SelectableFile> val files: List<SelectableFile>
@ -52,10 +44,6 @@ sealed class BrowseEvent {
val file: SelectableFile val file: SelectableFile
) : BrowseEvent() ) : BrowseEvent()
data class OnUpdateFavoriteDirectory(
val path: String
) : BrowseEvent()
data object OnShowFilterBottomSheet : BrowseEvent() data object OnShowFilterBottomSheet : BrowseEvent()
data object OnDismissBottomSheet : BrowseEvent() data object OnDismissBottomSheet : BrowseEvent()

View file

@ -24,13 +24,11 @@ import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield import kotlinx.coroutines.yield
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.browse.BrowseSortOrder import ua.acclorite.book_story.domain.browse.BrowseSortOrder
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.domain.library.book.NullableBook import ua.acclorite.book_story.domain.library.book.NullableBook
import ua.acclorite.book_story.domain.library.book.SelectableNullableBook import ua.acclorite.book_story.domain.library.book.SelectableNullableBook
import ua.acclorite.book_story.domain.use_case.book.InsertBook import ua.acclorite.book_story.domain.use_case.book.InsertBook
import ua.acclorite.book_story.domain.use_case.favorite_directory.UpdateFavoriteDirectory
import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile
import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
@ -43,7 +41,6 @@ import kotlin.collections.map
@HiltViewModel @HiltViewModel
class BrowseModel @Inject constructor( class BrowseModel @Inject constructor(
private val getFilesFromDevice: GetFilesFromDevice, private val getFilesFromDevice: GetFilesFromDevice,
private val updateFavoriteDirectory: UpdateFavoriteDirectory,
private val getBookFromFile: GetBookFromFile, private val getBookFromFile: GetBookFromFile,
private val insertBook: InsertBook private val insertBook: InsertBook
) : ViewModel() { ) : ViewModel() {
@ -69,7 +66,6 @@ class BrowseModel @Inject constructor(
private var refreshJob: Job? = null private var refreshJob: Job? = null
private var changeSearchQueryJob: Job? = null private var changeSearchQueryJob: Job? = null
private var changeDirectoryJob: Job? = null
private var storagePermissionJob: Job? = null private var storagePermissionJob: Job? = null
private var getAddDialogBooksJob: Job? = null private var getAddDialogBooksJob: Job? = null
@ -160,58 +156,27 @@ class BrowseModel @Inject constructor(
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
_state.update { _state.update {
it.copy( it.copy(
files = it.files.map { it.copy(isSelected = false) }, files = it.files.map { it.copy(selected = false) },
hasSelectedItems = false hasSelectedItems = false
) )
} }
} }
} }
is BrowseEvent.OnChangeDirectory -> {
viewModelScope.launch {
changeDirectoryJob?.cancel()
changeSearchQueryJob?.cancel()
changeDirectoryJob = launch(Dispatchers.IO) {
yield()
_state.update {
it.copy(
selectedDirectory = event.directory,
previousDirectory = if (event.savePreviousDirectory) it.selectedDirectory
else event.directory.parentFile,
inNestedDirectory = event.directory != Environment.getExternalStorageDirectory()
)
}
BrowseScreen.resetScrollPositionCompositionChannel.trySend(Unit)
}
}
}
is BrowseEvent.OnGoBackDirectory -> {
onEvent(
BrowseEvent.OnChangeDirectory(
_state.value.previousDirectory ?: Environment.getExternalStorageDirectory(),
savePreviousDirectory = false
)
)
}
is BrowseEvent.OnSelectFiles -> { is BrowseEvent.OnSelectFiles -> {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val editedList = _state.value.files.map { file -> val editedList = _state.value.files.map { file ->
if ( if (
event.files.any { event.files.any {
file.fileOrDirectory.path.startsWith(it.fileOrDirectory.path) file.path.startsWith(it.path)
} && event.includedFileFormats.run { } && event.includedFileFormats.run {
if (isEmpty()) return@run true if (isEmpty()) return@run true
any { any {
file.fileOrDirectory.path.endsWith( file.path.endsWith(it, ignoreCase = true)
it, ignoreCase = true
) || file.isDirectory
} }
} }
) { ) {
file.copy(isSelected = true) file.copy(selected = true)
} else { } else {
file file
} }
@ -221,13 +186,13 @@ class BrowseModel @Inject constructor(
it.copy( it.copy(
files = editedList, files = editedList,
selectedItemsCount = editedList.filter { file -> selectedItemsCount = editedList.filter { file ->
file.isSelected && !file.isDirectory file.selected
}.size.run { }.size.run {
if (this == 0) return@run it.selectedItemsCount if (this == 0) return@run it.selectedItemsCount
this this
}, },
hasSelectedItems = editedList.any { file -> hasSelectedItems = editedList.any { file ->
file.isSelected && !file.isDirectory file.selected
} }
) )
} }
@ -237,37 +202,12 @@ class BrowseModel @Inject constructor(
is BrowseEvent.OnSelectFile -> { is BrowseEvent.OnSelectFile -> {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val editedList = _state.value.files.map { file -> val editedList = _state.value.files.map { file ->
when (event.file.isDirectory) { if (event.file.path == file.path) {
false -> { file.copy(
if (event.file.fileOrDirectory.path == file.fileOrDirectory.path) { selected = !file.selected
file.copy( )
isSelected = !file.isSelected } else {
) file
} else {
file
}
}
true -> {
if (
file.fileOrDirectory.path.startsWith(
event.file.fileOrDirectory.path
) && event.includedFileFormats.run {
if (isEmpty()) return@run true
any {
file.fileOrDirectory.path.endsWith(
it, ignoreCase = true
) || file.isDirectory
}
}
) {
file.copy(
isSelected = !event.file.isSelected
)
} else {
file
}
}
} }
} }
@ -275,29 +215,19 @@ class BrowseModel @Inject constructor(
it.copy( it.copy(
files = editedList, files = editedList,
selectedItemsCount = editedList.filter { file -> selectedItemsCount = editedList.filter { file ->
file.isSelected && !file.isDirectory file.selected
}.size.run { }.size.run {
if (this == 0) return@run it.selectedItemsCount if (this == 0) return@run it.selectedItemsCount
this this
}, },
hasSelectedItems = editedList.any { file -> hasSelectedItems = editedList.any { file ->
file.isSelected && !file.isDirectory file.selected
} }
) )
} }
} }
} }
is BrowseEvent.OnUpdateFavoriteDirectory -> {
viewModelScope.launch {
_state.update {
it.copy(isLoading = true)
}
updateFavoriteDirectory.execute(event.path)
getFilesFromDownloads()
}
}
is BrowseEvent.OnShowFilterBottomSheet -> { is BrowseEvent.OnShowFilterBottomSheet -> {
viewModelScope.launch { viewModelScope.launch {
_state.update { _state.update {
@ -463,7 +393,7 @@ class BrowseModel @Inject constructor(
val books = mutableListOf<NullableBook>() val books = mutableListOf<NullableBook>()
_state.value.files _state.value.files
.filter { it.isSelected && !it.isDirectory } .filter { it.selected }
.ifEmpty { .ifEmpty {
_state.update { _state.update {
it.copy( it.copy(
@ -473,7 +403,7 @@ class BrowseModel @Inject constructor(
} }
return@launch return@launch
} }
.map { it.fileOrDirectory } .map { File(it.path) }
.forEach { .forEach {
yield() yield()
books.add(getBookFromFile.execute(it)) books.add(getBookFromFile.execute(it))
@ -609,7 +539,6 @@ class BrowseModel @Inject constructor(
it.copy( it.copy(
files = this, files = this,
selectedItemsCount = 0, selectedItemsCount = 0,
hasSearched = query.isNotBlank(),
hasSelectedItems = false, hasSelectedItems = false,
isLoading = false isLoading = false
) )
@ -626,15 +555,11 @@ class BrowseModel @Inject constructor(
fun filterList( fun filterList(
files: List<SelectableFile>, files: List<SelectableFile>,
hasSearched: Boolean,
selectedDirectory: File,
pinFavoriteDirectories: Boolean,
sortOrderDescending: Boolean, sortOrderDescending: Boolean,
includedFilterItems: List<String>, includedFilterItems: List<String>,
filesStructure: BrowseFilesStructure,
sortOrder: BrowseSortOrder sortOrder: BrowseSortOrder
): List<SelectableFile> { ): List<SelectableFile> {
fun <T> thenCompareBy( fun <T> compareByWithOrder(
selector: (T) -> Comparable<*>? selector: (T) -> Comparable<*>?
): Comparator<T> { ): Comparator<T> {
return if (sortOrderDescending) { return if (sortOrderDescending) {
@ -650,83 +575,36 @@ class BrowseModel @Inject constructor(
} }
return filter { file -> return filter { file ->
when (file.isDirectory) { includedFilterItems.any {
true -> { file.path.endsWith(
return@filter this.filter { it, ignoreCase = true
if (file == it) { )
return@filter false
}
it.fileOrDirectory.path.startsWith(file.fileOrDirectory.path)
}.filterFiles().isNotEmpty()
}
false -> {
return@filter includedFilterItems.any {
file.fileOrDirectory.path.endsWith(
it, ignoreCase = true
)
}
}
} }
} }
} }
return files return files
.filterFiles() .filterFiles()
.filter {
if (hasSearched || filesStructure == BrowseFilesStructure.ALL_FILES) {
return@filter !it.isDirectory
}
if (
Environment.getExternalStorageDirectory() == selectedDirectory
&& it.isFavorite
&& pinFavoriteDirectories
) {
return@filter true
}
it.parentDirectory == selectedDirectory
}
.sortedWith( .sortedWith(
compareByDescending<SelectableFile> { compareByWithOrder<SelectableFile> {
when (pinFavoriteDirectories) { when (sortOrder) {
true -> it.isFavorite BrowseSortOrder.NAME -> {
false -> true it.name.trim()
} }
}.then(
compareByDescending { BrowseSortOrder.FILE_FORMAT -> {
when (sortOrder != BrowseSortOrder.FILE_TYPE) { it.path.substringAfterLast(".").lowercase().trimEnd()
true -> it.isDirectory }
false -> true
BrowseSortOrder.FILE_SIZE -> {
it.size
}
else -> {
it.lastModified
} }
} }
).then( }
thenCompareBy {
when (sortOrder) {
BrowseSortOrder.NAME -> {
it.fileOrDirectory.name.lowercase().trim()
}
BrowseSortOrder.FILE_TYPE -> {
it.isDirectory
}
BrowseSortOrder.FILE_FORMAT -> {
it.fileOrDirectory.extension
}
BrowseSortOrder.FILE_SIZE -> {
it.fileOrDirectory.length()
}
BrowseSortOrder.LAST_MODIFIED -> {
it.fileOrDirectory.lastModified()
}
}
}
)
) )
} }

View file

@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.browse.BrowseLayout import ua.acclorite.book_story.domain.browse.BrowseLayout
import ua.acclorite.book_story.domain.navigator.Screen import ua.acclorite.book_story.domain.navigator.Screen
import ua.acclorite.book_story.presentation.browse.BrowseContent import ua.acclorite.book_story.presentation.browse.BrowseContent
@ -93,12 +92,8 @@ object BrowseScreen : Screen, Parcelable {
derivedStateOf { derivedStateOf {
screenModel.filterList( screenModel.filterList(
files = state.value.files, files = state.value.files,
hasSearched = state.value.hasSearched,
selectedDirectory = state.value.selectedDirectory,
pinFavoriteDirectories = mainState.value.browsePinFavoriteDirectories,
sortOrderDescending = mainState.value.browseSortOrderDescending, sortOrderDescending = mainState.value.browseSortOrderDescending,
includedFilterItems = mainState.value.browseIncludedFilterItems, includedFilterItems = mainState.value.browseIncludedFilterItems,
filesStructure = mainState.value.browseFilesStructure,
sortOrder = mainState.value.browseSortOrder sortOrder = mainState.value.browseSortOrder
) )
} }
@ -155,15 +150,11 @@ object BrowseScreen : Screen, Parcelable {
listState = listState, listState = listState,
gridState = gridState, gridState = gridState,
layout = mainState.value.browseLayout, layout = mainState.value.browseLayout,
filesStructure = mainState.value.browseFilesStructure,
gridSize = mainState.value.browseGridSize, gridSize = mainState.value.browseGridSize,
autoGridSize = mainState.value.browseAutoGridSize, autoGridSize = mainState.value.browseAutoGridSize,
includedFilterItems = mainState.value.browseIncludedFilterItems, includedFilterItems = mainState.value.browseIncludedFilterItems,
canScrollBackList = listState.canScrollBackward, canScrollBackList = listState.canScrollBackward,
canScrollBackGrid = gridState.canScrollBackward, canScrollBackGrid = gridState.canScrollBackward,
selectedDirectory = state.value.selectedDirectory,
inNestedDirectory = state.value.inNestedDirectory
&& mainState.value.browseFilesStructure != BrowseFilesStructure.ALL_FILES,
hasSelectedItems = state.value.hasSelectedItems, hasSelectedItems = state.value.hasSelectedItems,
selectedItemsCount = state.value.selectedItemsCount, selectedItemsCount = state.value.selectedItemsCount,
isRefreshing = state.value.isRefreshing, isRefreshing = state.value.isRefreshing,
@ -173,19 +164,15 @@ object BrowseScreen : Screen, Parcelable {
filesEmpty = files.value.isEmpty(), filesEmpty = files.value.isEmpty(),
showSearch = state.value.showSearch, showSearch = state.value.showSearch,
searchQuery = state.value.searchQuery, searchQuery = state.value.searchQuery,
hasSearched = state.value.hasSearched,
focusRequester = focusRequester, focusRequester = focusRequester,
searchVisibility = screenModel::onEvent, searchVisibility = screenModel::onEvent,
searchQueryChange = screenModel::onEvent, searchQueryChange = screenModel::onEvent,
search = screenModel::onEvent, search = screenModel::onEvent,
requestFocus = screenModel::onEvent, requestFocus = screenModel::onEvent,
clearSelectedFiles = screenModel::onEvent, clearSelectedFiles = screenModel::onEvent,
goBackDirectory = screenModel::onEvent,
selectFiles = screenModel::onEvent, selectFiles = screenModel::onEvent,
selectFile = screenModel::onEvent, selectFile = screenModel::onEvent,
permissionCheck = screenModel::onEvent, permissionCheck = screenModel::onEvent,
changeDirectory = screenModel::onEvent,
updateFavoriteDirectory = screenModel::onEvent,
showFilterBottomSheet = screenModel::onEvent, showFilterBottomSheet = screenModel::onEvent,
dismissBottomSheet = screenModel::onEvent, dismissBottomSheet = screenModel::onEvent,
actionPermissionDialog = screenModel::onEvent, actionPermissionDialog = screenModel::onEvent,

View file

@ -1,21 +1,15 @@
package ua.acclorite.book_story.ui.browse package ua.acclorite.book_story.ui.browse
import android.os.Environment
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.domain.browse.SelectableFile import ua.acclorite.book_story.domain.browse.SelectableFile
import ua.acclorite.book_story.domain.library.book.SelectableNullableBook import ua.acclorite.book_story.domain.library.book.SelectableNullableBook
import ua.acclorite.book_story.domain.util.BottomSheet import ua.acclorite.book_story.domain.util.BottomSheet
import ua.acclorite.book_story.domain.util.Dialog import ua.acclorite.book_story.domain.util.Dialog
import java.io.File
@Immutable @Immutable
data class BrowseState( data class BrowseState(
val files: List<SelectableFile> = emptyList(), val files: List<SelectableFile> = emptyList(),
val selectedDirectory: File = Environment.getExternalStorageDirectory(),
val previousDirectory: File? = null,
val inNestedDirectory: Boolean = false,
val isLoading: Boolean = true, val isLoading: Boolean = true,
val isRefreshing: Boolean = false, val isRefreshing: Boolean = false,
val isError: Boolean = false, val isError: Boolean = false,
@ -25,7 +19,6 @@ data class BrowseState(
val showSearch: Boolean = false, val showSearch: Boolean = false,
val searchQuery: String = "", val searchQuery: String = "",
val hasSearched: Boolean = false,
val hasFocused: Boolean = false, val hasFocused: Boolean = false,
val dialog: Dialog? = null, val dialog: Dialog? = null,

View file

@ -20,11 +20,9 @@ sealed class MainEvent {
data class OnChangeSidePadding(val value: Int) : MainEvent() data class OnChangeSidePadding(val value: Int) : MainEvent()
data class OnChangeDoubleClickTranslation(val value: Boolean) : MainEvent() data class OnChangeDoubleClickTranslation(val value: Boolean) : MainEvent()
data class OnChangeFastColorPresetChange(val value: Boolean) : MainEvent() data class OnChangeFastColorPresetChange(val value: Boolean) : MainEvent()
data class OnChangeBrowseFilesStructure(val value: String) : MainEvent()
data class OnChangeBrowseLayout(val value: String) : MainEvent() data class OnChangeBrowseLayout(val value: String) : MainEvent()
data class OnChangeBrowseAutoGridSize(val value: Boolean) : MainEvent() data class OnChangeBrowseAutoGridSize(val value: Boolean) : MainEvent()
data class OnChangeBrowseGridSize(val value: Int) : MainEvent() data class OnChangeBrowseGridSize(val value: Int) : MainEvent()
data class OnChangeBrowsePinFavoriteDirectories(val value: Boolean) : MainEvent()
data class OnChangeBrowseSortOrder(val value: String) : MainEvent() data class OnChangeBrowseSortOrder(val value: String) : MainEvent()
data class OnChangeBrowseSortOrderDescending(val value: Boolean) : MainEvent() data class OnChangeBrowseSortOrderDescending(val value: Boolean) : MainEvent()
data class OnChangeBrowseIncludedFilterItem(val value: String) : MainEvent() data class OnChangeBrowseIncludedFilterItem(val value: String) : MainEvent()

View file

@ -16,7 +16,6 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield import kotlinx.coroutines.yield
import ua.acclorite.book_story.domain.browse.toBrowseFilesStructure
import ua.acclorite.book_story.domain.browse.toBrowseLayout import ua.acclorite.book_story.domain.browse.toBrowseLayout
import ua.acclorite.book_story.domain.browse.toBrowseSortOrder import ua.acclorite.book_story.domain.browse.toBrowseSortOrder
import ua.acclorite.book_story.domain.reader.toColorEffects import ua.acclorite.book_story.domain.reader.toColorEffects
@ -189,14 +188,6 @@ class MainModel @Inject constructor(
} }
) )
is MainEvent.OnChangeBrowseFilesStructure -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_FILES_STRUCTURE,
value = event.value,
updateState = {
it.copy(browseFilesStructure = toBrowseFilesStructure())
}
)
is MainEvent.OnChangeBrowseLayout -> handleDatastoreUpdate( is MainEvent.OnChangeBrowseLayout -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_LAYOUT, key = DataStoreConstants.BROWSE_LAYOUT,
value = event.value, value = event.value,
@ -221,14 +212,6 @@ class MainModel @Inject constructor(
} }
) )
is MainEvent.OnChangeBrowsePinFavoriteDirectories -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_PIN_FAVORITE_DIRECTORIES,
value = event.value,
updateState = {
it.copy(browsePinFavoriteDirectories = this)
}
)
is MainEvent.OnChangeBrowseSortOrder -> handleDatastoreUpdate( is MainEvent.OnChangeBrowseSortOrder -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_SORT_ORDER, key = DataStoreConstants.BROWSE_SORT_ORDER,
value = event.value, value = event.value,

View file

@ -7,10 +7,8 @@ import androidx.annotation.Keep
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import ua.acclorite.book_story.domain.browse.BrowseFilesStructure
import ua.acclorite.book_story.domain.browse.BrowseLayout import ua.acclorite.book_story.domain.browse.BrowseLayout
import ua.acclorite.book_story.domain.browse.BrowseSortOrder import ua.acclorite.book_story.domain.browse.BrowseSortOrder
import ua.acclorite.book_story.domain.browse.toBrowseFilesStructure
import ua.acclorite.book_story.domain.browse.toBrowseLayout import ua.acclorite.book_story.domain.browse.toBrowseLayout
import ua.acclorite.book_story.domain.browse.toBrowseSortOrder import ua.acclorite.book_story.domain.browse.toBrowseSortOrder
import ua.acclorite.book_story.domain.reader.ReaderColorEffects import ua.acclorite.book_story.domain.reader.ReaderColorEffects
@ -108,13 +106,9 @@ data class MainState(
val progressBarFontSize: Int = provideDefaultValue { 8 }, val progressBarFontSize: Int = provideDefaultValue { 8 },
// Browse Settings // Browse Settings
val browseFilesStructure: BrowseFilesStructure = provideDefaultValue {
BrowseFilesStructure.DIRECTORIES
},
val browseLayout: BrowseLayout = provideDefaultValue { BrowseLayout.LIST }, val browseLayout: BrowseLayout = provideDefaultValue { BrowseLayout.LIST },
val browseAutoGridSize: Boolean = provideDefaultValue { true }, val browseAutoGridSize: Boolean = provideDefaultValue { true },
val browseGridSize: Int = provideDefaultValue { 0 }, val browseGridSize: Int = provideDefaultValue { 0 },
val browsePinFavoriteDirectories: Boolean = provideDefaultValue { true },
val browseSortOrder: BrowseSortOrder = provideDefaultValue { BrowseSortOrder.LAST_MODIFIED }, val browseSortOrder: BrowseSortOrder = provideDefaultValue { BrowseSortOrder.LAST_MODIFIED },
val browseSortOrderDescending: Boolean = provideDefaultValue { true }, val browseSortOrderDescending: Boolean = provideDefaultValue { true },
val browseIncludedFilterItems: List<String> = provideDefaultValue { emptyList() }, val browseIncludedFilterItems: List<String> = provideDefaultValue { emptyList() },
@ -208,10 +202,6 @@ data class MainState(
FAST_COLOR_PRESET_CHANGE FAST_COLOR_PRESET_CHANGE
) { fastColorPresetChange }, ) { fastColorPresetChange },
browseFilesStructure = provideValue(
BROWSE_FILES_STRUCTURE, convert = { toBrowseFilesStructure() }
) { browseFilesStructure },
browseLayout = provideValue( browseLayout = provideValue(
BROWSE_LAYOUT, convert = { toBrowseLayout() } BROWSE_LAYOUT, convert = { toBrowseLayout() }
) { browseLayout }, ) { browseLayout },
@ -224,10 +214,6 @@ data class MainState(
BROWSE_GRID_SIZE BROWSE_GRID_SIZE
) { browseGridSize }, ) { browseGridSize },
browsePinFavoriteDirectories = provideValue(
BROWSE_PIN_FAVORITE_DIRECTORIES
) { browsePinFavoriteDirectories },
browseSortOrder = provideValue( browseSortOrder = provideValue(
BROWSE_SORT_ORDER, convert = { toBrowseSortOrder() } BROWSE_SORT_ORDER, convert = { toBrowseSortOrder() }
) { browseSortOrder }, ) { browseSortOrder },

View file

@ -128,13 +128,9 @@
<string name="error_no_dictionary">لم يتم العثور على تطبيق قاموس.</string> <string name="error_no_dictionary">لم يتم العثور على تطبيق قاموس.</string>
<string name="error_no_share_app">لم يتم العثور على تطبيق للمشاركة.</string> <string name="error_no_share_app">لم يتم العثور على تطبيق للمشاركة.</string>
<string name="font_style_italic">مائل</string> <string name="font_style_italic">مائل</string>
<string name="files_structure_all">كل الملفات</string>
<string name="files_structure_directory">المجلدات</string>
<string name="browse_pin_favorite_directories_option_desc">تثبيت مجلداتك المفضلة في أعلى الشاشة</string>
<string name="green_color">أخضر</string> <string name="green_color">أخضر</string>
<string name="red_color">أحمر</string> <string name="red_color">أحمر</string>
<string name="blue_color">أزرق</string> <string name="blue_color">أزرق</string>
<string name="browse_pin_favorite_directories_option">تثبيت المجلدات المفضلة</string>
<string name="pure_dark_off">معطل</string> <string name="pure_dark_off">معطل</string>
<string name="dynamic_theme">عطارد</string> <string name="dynamic_theme">عطارد</string>
<string name="pink_theme">زحل</string> <string name="pink_theme">زحل</string>
@ -151,7 +147,6 @@
<string name="browse_grid_size_auto">اوتوماتيكي</string> <string name="browse_grid_size_auto">اوتوماتيكي</string>
<string name="browse_grid_size_per_row">بالسطر</string> <string name="browse_grid_size_per_row">بالسطر</string>
<string name="browse_sort_order_name">أبجديا</string> <string name="browse_sort_order_name">أبجديا</string>
<string name="browse_sort_order_file_type">نوع الملف</string>
<string name="blue_theme">نبتون</string> <string name="blue_theme">نبتون</string>
<string name="red_theme">المريخ</string> <string name="red_theme">المريخ</string>
<string name="purple_theme">المشتري</string> <string name="purple_theme">المشتري</string>
@ -197,7 +192,6 @@
<string name="pure_dark_power_saver">توفير</string> <string name="pure_dark_power_saver">توفير</string>
<string name="browse_sort_order_last_modified">آخر تعديل</string> <string name="browse_sort_order_last_modified">آخر تعديل</string>
<string name="text_alignment_option">مواءمة النص</string> <string name="text_alignment_option">مواءمة النص</string>
<string name="browse_files_structure_option">هيكل الملفات</string>
<string name="double_press_exit_option">اضغط مرة أخرى مزدوجة للخروج</string> <string name="double_press_exit_option">اضغط مرة أخرى مزدوجة للخروج</string>
<string name="double_press_exit_option_desc">اضغط مرتين للخروج من التطبيق</string> <string name="double_press_exit_option_desc">اضغط مرتين للخروج من التطبيق</string>
<string name="letter_spacing_option">تباعد الحروف</string> <string name="letter_spacing_option">تباعد الحروف</string>
@ -241,7 +235,6 @@
<string name="theme_contrast_standard">الافتراضي</string> <string name="theme_contrast_standard">الافتراضي</string>
<string name="screen_brightness_option">السطوع</string> <string name="screen_brightness_option">السطوع</string>
<string name="pink2_theme">غانيميد</string> <string name="pink2_theme">غانيميد</string>
<string name="internal_storage">التخزين الداخلي</string>
<string name="file_last_opened">اخر مرة تم فيها فتح الملف</string> <string name="file_last_opened">اخر مرة تم فيها فتح الملف</string>
<string name="chapters">فصول</string> <string name="chapters">فصول</string>
<string name="red_gray_theme">كاليستو</string> <string name="red_gray_theme">كاليستو</string>

View file

@ -61,7 +61,6 @@
<string name="app_version_option">Verze aplikace</string> <string name="app_version_option">Verze aplikace</string>
<string name="help_desc_how_to_add_books_4">Knihovna</string> <string name="help_desc_how_to_add_books_4">Knihovna</string>
<string name="help_translate_option">Pomozte překládat</string> <string name="help_translate_option">Pomozte překládat</string>
<string name="files_structure_directory">Složky</string>
<string name="filter_tab">Filtr</string> <string name="filter_tab">Filtr</string>
<string name="reader_tab">Čtečka</string> <string name="reader_tab">Čtečka</string>
<string name="update_query">Aktualizace %1$s</string> <string name="update_query">Aktualizace %1$s</string>
@ -122,7 +121,6 @@
<string name="double_click_translation_option">Překlad na dvojité kliknutí</string> <string name="double_click_translation_option">Překlad na dvojité kliknutí</string>
<string name="keep_screen_on_option">Nechat obrazovku zapnutou</string> <string name="keep_screen_on_option">Nechat obrazovku zapnutou</string>
<string name="browse_sort_order_file_format">Formát souboru</string> <string name="browse_sort_order_file_format">Formát souboru</string>
<string name="browse_sort_order_file_type">Typ souboru</string>
<string name="browse_sort_order_file_size">Velikost souboru</string> <string name="browse_sort_order_file_size">Velikost souboru</string>
<string name="alignment_start">Začátek</string> <string name="alignment_start">Začátek</string>
<string name="alignment_end">Konec</string> <string name="alignment_end">Konec</string>
@ -137,7 +135,6 @@
<string name="report_bug_option">Nahlásit chybu</string> <string name="report_bug_option">Nahlásit chybu</string>
<string name="credits_option">Zdroje</string> <string name="credits_option">Zdroje</string>
<string name="contributors_option">Spolupracovníci</string> <string name="contributors_option">Spolupracovníci</string>
<string name="internal_storage">Interní úložiště</string>
<string name="delete_books_description">Smaže to všechny vybrané knihy( %1$s) z databáze. Nesmaže to knihy ze zařízení.</string> <string name="delete_books_description">Smaže to všechny vybrané knihy( %1$s) z databáze. Nesmaže to knihy ze zařízení.</string>
<string name="never">Nikdy</string> <string name="never">Nikdy</string>
<string name="settings_screen">Nastavení</string> <string name="settings_screen">Nastavení</string>
@ -182,7 +179,6 @@
<string name="colors_appearance_settings">Barvy</string> <string name="colors_appearance_settings">Barvy</string>
<string name="font_size_option">Velikost fontu</string> <string name="font_size_option">Velikost fontu</string>
<string name="paragraph_height_option">Výška odstavce</string> <string name="paragraph_height_option">Výška odstavce</string>
<string name="browse_pin_favorite_directories_option">Připnout oblíbené složky</string>
<string name="blue_color">Modrá</string> <string name="blue_color">Modrá</string>
<string name="app_version_option_desc_1">Book\'s Story v%1$s</string> <string name="app_version_option_desc_1">Book\'s Story v%1$s</string>
<string name="absolute_dark_option_desc">Změnit barvu pozadí na čistě černou</string> <string name="absolute_dark_option_desc">Změnit barvu pozadí na čistě černou</string>
@ -196,12 +192,10 @@
<string name="reset_cover">Resetovat obálku</string> <string name="reset_cover">Resetovat obálku</string>
<string name="app_version_option_desc_2">Klepněte pro zkontrolování aktualizací</string> <string name="app_version_option_desc_2">Klepněte pro zkontrolování aktualizací</string>
<string name="help_desc_how_to_customize_app_1">Přejít na</string> <string name="help_desc_how_to_customize_app_1">Přejít na</string>
<string name="browse_files_structure_option">Struktura souborů</string>
<string name="dark_theme_on">Zapnutý</string> <string name="dark_theme_on">Zapnutý</string>
<string name="pure_dark_power_saver">Spořič</string> <string name="pure_dark_power_saver">Spořič</string>
<string name="theme_contrast_medium">Střední</string> <string name="theme_contrast_medium">Střední</string>
<string name="theme_contrast_high">Vysoký</string> <string name="theme_contrast_high">Vysoký</string>
<string name="files_structure_all">Všechny soubory</string>
<string name="browse_grid_size_per_row">na řádku</string> <string name="browse_grid_size_per_row">na řádku</string>
<string name="alignment_justify">Zarovnat</string> <string name="alignment_justify">Zarovnat</string>
<string name="alignment_center">Do prostřed</string> <string name="alignment_center">Do prostřed</string>
@ -225,8 +219,6 @@
<string name="start_permissions_storage_desc">Vyžadováno, abychom mohli skenoval Vaše úložiště a hledat knihy</string> <string name="start_permissions_storage_desc">Vyžadováno, abychom mohli skenoval Vaše úložiště a hledat knihy</string>
<string name="start_language_preferences">Preference jazyka</string> <string name="start_language_preferences">Preference jazyka</string>
<string name="start_theme_preferences">Preference témat</string> <string name="start_theme_preferences">Preference témat</string>
<string name="directory_icon_content_desc">Složka</string>
<string name="favorite_directory_content_desc">Oblíbená složka</string>
<string name="history_content_desc">Historie čtení</string> <string name="history_content_desc">Historie čtení</string>
<string name="sort_order_content_desc">Řadit podle</string> <string name="sort_order_content_desc">Řadit podle</string>
<string name="cover_image_content_desc">Obálka</string> <string name="cover_image_content_desc">Obálka</string>

View file

@ -254,7 +254,6 @@
<string name="tryzub_content_desc">Dreizack</string> <string name="tryzub_content_desc">Dreizack</string>
<string name="github_profile_content_desc">GitHub Profil</string> <string name="github_profile_content_desc">GitHub Profil</string>
<string name="drag_content_desc">Ziehen</string> <string name="drag_content_desc">Ziehen</string>
<string name="internal_storage">Interner Speicher</string>
<string name="filter_content_desc">Filter</string> <string name="filter_content_desc">Filter</string>
<string name="filter_tab">Filter</string> <string name="filter_tab">Filter</string>
<string name="sort_tab">Sortieren</string> <string name="sort_tab">Sortieren</string>
@ -264,31 +263,22 @@
<string name="sort_browse_settings">Sortieren</string> <string name="sort_browse_settings">Sortieren</string>
<string name="browse_layout_option">Anzeigemodus</string> <string name="browse_layout_option">Anzeigemodus</string>
<string name="browse_grid_size_option">Rastergröße</string> <string name="browse_grid_size_option">Rastergröße</string>
<string name="files_structure_all">Alle Dateien</string>
<string name="files_structure_directory">Verzeichnisse</string>
<string name="browse_layout_list">Liste</string> <string name="browse_layout_list">Liste</string>
<string name="browse_layout_grid">Raster</string> <string name="browse_layout_grid">Raster</string>
<string name="browse_grid_size_auto">Auto</string> <string name="browse_grid_size_auto">Auto</string>
<string name="browse_grid_size_per_row">Pro Reihe</string> <string name="browse_grid_size_per_row">Pro Reihe</string>
<string name="browse_sort_order_name">Alphabetisch</string> <string name="browse_sort_order_name">Alphabetisch</string>
<string name="browse_sort_order_file_format">Dateiformat</string> <string name="browse_sort_order_file_format">Dateiformat</string>
<string name="browse_sort_order_file_type">Dateityp</string>
<string name="directory_icon_content_desc">Ordner</string>
<string name="favorite_directory_content_desc">Lieblingsordner</string>
<string name="sort_order_content_desc">Sortierung</string> <string name="sort_order_content_desc">Sortierung</string>
<string name="path_arrow_icon_content_desc">Pfadpfeil</string>
<string name="select_all_files_content_desc">Alle Dateien auswählen</string> <string name="select_all_files_content_desc">Alle Dateien auswählen</string>
<string name="error_no_share_app">Keine App zum Teilen gefunden.</string> <string name="error_no_share_app">Keine App zum Teilen gefunden.</string>
<string name="error_no_dictionary">Keine Wörterbuch-App gefunden.</string> <string name="error_no_dictionary">Keine Wörterbuch-App gefunden.</string>
<string name="web_search">Websuche</string> <string name="web_search">Websuche</string>
<string name="share">Teilen</string> <string name="share">Teilen</string>
<string name="general_browse_settings">Allgemein</string> <string name="general_browse_settings">Allgemein</string>
<string name="browse_pin_favorite_directories_option">Lieblingsverzeichnisse anpinnen</string>
<string name="browse_pin_favorite_directories_option_desc">Heften Sie Ihre Lieblingsverzeichnisse oben auf dem Bildschirm an</string>
<string name="browse_sort_order_last_modified">Zuletzt geändert</string> <string name="browse_sort_order_last_modified">Zuletzt geändert</string>
<string name="browse_sort_order_file_size">Dateigröße</string> <string name="browse_sort_order_file_size">Dateigröße</string>
<string name="text_alignment_option">Textausrichtung</string> <string name="text_alignment_option">Textausrichtung</string>
<string name="browse_files_structure_option">Dateistruktur</string>
<string name="alignment_start">Start</string> <string name="alignment_start">Start</string>
<string name="alignment_justify">Rechtfertigen</string> <string name="alignment_justify">Rechtfertigen</string>
<string name="alignment_center">Mitte</string> <string name="alignment_center">Mitte</string>

View file

@ -260,11 +260,7 @@
<string name="browse_layout_grid">Cuadrícula</string> <string name="browse_layout_grid">Cuadrícula</string>
<string name="browse_grid_size_per_row">por fila</string> <string name="browse_grid_size_per_row">por fila</string>
<string name="browse_sort_order_file_size">Tamaño del archivo</string> <string name="browse_sort_order_file_size">Tamaño del archivo</string>
<string name="internal_storage">Almacenamiento interno</string>
<string name="directory_icon_content_desc">Directorio</string>
<string name="favorite_directory_content_desc">Directorio preferido</string>
<string name="sort_order_content_desc">Orden de clasificación</string> <string name="sort_order_content_desc">Orden de clasificación</string>
<string name="path_arrow_icon_content_desc">Flecha de trayectoria</string>
<string name="error_no_share_app">No se ha encontrado ninguna aplicación para compartir.</string> <string name="error_no_share_app">No se ha encontrado ninguna aplicación para compartir.</string>
<string name="error_no_dictionary">No se ha encontrado ninguna aplicación de diccionario.</string> <string name="error_no_dictionary">No se ha encontrado ninguna aplicación de diccionario.</string>
<string name="web_search">Buscar en Internet</string> <string name="web_search">Buscar en Internet</string>
@ -275,12 +271,7 @@
<string name="filter_browse_settings">Filtrar</string> <string name="filter_browse_settings">Filtrar</string>
<string name="sort_browse_settings">Clasificar</string> <string name="sort_browse_settings">Clasificar</string>
<string name="browse_layout_option">Modo de visualización</string> <string name="browse_layout_option">Modo de visualización</string>
<string name="browse_pin_favorite_directories_option">Fijar directorios favoritos</string>
<string name="files_structure_all">Todos los archivos</string>
<string name="browse_layout_list">Lista</string> <string name="browse_layout_list">Lista</string>
<string name="browse_pin_favorite_directories_option_desc">Fija tus directorios favoritos en la parte superior de la pantalla</string>
<string name="files_structure_directory">Directorios</string>
<string name="browse_sort_order_file_type">Tipo de archivo</string>
<string name="browse_grid_size_auto">Auto</string> <string name="browse_grid_size_auto">Auto</string>
<string name="browse_sort_order_file_format">Formato del archivo</string> <string name="browse_sort_order_file_format">Formato del archivo</string>
<string name="browse_sort_order_name">Alfabéticamente</string> <string name="browse_sort_order_name">Alfabéticamente</string>
@ -288,7 +279,6 @@
<string name="select_all_files_content_desc">Seleccionar todos los archivos</string> <string name="select_all_files_content_desc">Seleccionar todos los archivos</string>
<string name="filter_content_desc">Filtrar</string> <string name="filter_content_desc">Filtrar</string>
<string name="text_alignment_option">Alineación del texto</string> <string name="text_alignment_option">Alineación del texto</string>
<string name="browse_files_structure_option">Estructura de los ficheros</string>
<string name="alignment_start">Iniciar</string> <string name="alignment_start">Iniciar</string>
<string name="alignment_justify">Justificar</string> <string name="alignment_justify">Justificar</string>
<string name="alignment_center">Centrar</string> <string name="alignment_center">Centrar</string>

View file

@ -92,11 +92,8 @@
<string name="fast_color_preset_change_option_desc">Balayez la barre supérieure à gauche ou à droite pour changer de couleur par défaut</string> <string name="fast_color_preset_change_option_desc">Balayez la barre supérieure à gauche ou à droite pour changer de couleur par défaut</string>
<string name="text_alignment_option">Alignement du texte</string> <string name="text_alignment_option">Alignement du texte</string>
<string name="letter_spacing_option">Espacement des lettres</string> <string name="letter_spacing_option">Espacement des lettres</string>
<string name="browse_files_structure_option">Structure des fichiers</string>
<string name="browse_layout_option">Mode d\'affichage</string> <string name="browse_layout_option">Mode d\'affichage</string>
<string name="browse_grid_size_option">Taille de la grille</string> <string name="browse_grid_size_option">Taille de la grille</string>
<string name="browse_pin_favorite_directories_option">Épingler les répertoires favoris</string>
<string name="browse_pin_favorite_directories_option_desc">Épinglez vos répertoires préférés en haut de l\'écran</string>
<string name="red_color">Rouge</string> <string name="red_color">Rouge</string>
<string name="green_color">Vert</string> <string name="green_color">Vert</string>
<string name="blue_color">Bleu</string> <string name="blue_color">Bleu</string>
@ -110,12 +107,10 @@
<string name="theme_contrast_high">Élevé</string> <string name="theme_contrast_high">Élevé</string>
<string name="font_style_italic">Italique</string> <string name="font_style_italic">Italique</string>
<string name="font_style_normal">Normal</string> <string name="font_style_normal">Normal</string>
<string name="files_structure_all">Tous les fichiers</string>
<string name="browse_layout_list">Liste</string> <string name="browse_layout_list">Liste</string>
<string name="browse_layout_grid">Grille</string> <string name="browse_layout_grid">Grille</string>
<string name="browse_grid_size_auto">Automatique</string> <string name="browse_grid_size_auto">Automatique</string>
<string name="browse_grid_size_per_row">par ligne</string> <string name="browse_grid_size_per_row">par ligne</string>
<string name="browse_sort_order_file_type">Type de fichier</string>
<string name="browse_sort_order_last_modified">Dernière modification</string> <string name="browse_sort_order_last_modified">Dernière modification</string>
<string name="browse_sort_order_file_size">Taille de fichier</string> <string name="browse_sort_order_file_size">Taille de fichier</string>
<string name="alignment_start">Début</string> <string name="alignment_start">Début</string>
@ -149,7 +144,6 @@
<string name="file_last_opened">Dernier fichier ouvert</string> <string name="file_last_opened">Dernier fichier ouvert</string>
<string name="file_size">Taille du fichier</string> <string name="file_size">Taille du fichier</string>
<string name="unknown">Inconnu</string> <string name="unknown">Inconnu</string>
<string name="internal_storage">Stockage interne</string>
<string name="app_version_option_desc_1">Book\'s Story v%1$s</string> <string name="app_version_option_desc_1">Book\'s Story v%1$s</string>
<string name="app_version_option_desc_2">Cliquez pour vérifier les mises à jour</string> <string name="app_version_option_desc_2">Cliquez pour vérifier les mises à jour</string>
<string name="report_bug_option">Signaler un bug</string> <string name="report_bug_option">Signaler un bug</string>
@ -206,8 +200,6 @@
<string name="go_back_content_desc">Retourner</string> <string name="go_back_content_desc">Retourner</string>
<string name="cover_image_content_desc">Image de couverture</string> <string name="cover_image_content_desc">Image de couverture</string>
<string name="file_icon_content_desc">Fichier</string> <string name="file_icon_content_desc">Fichier</string>
<string name="directory_icon_content_desc">Répertoire</string>
<string name="path_arrow_icon_content_desc">Flèche du chemin</string>
<string name="checkbox_content_desc">Case à cocher</string> <string name="checkbox_content_desc">Case à cocher</string>
<string name="cover_image_not_found_content_desc">L\'image de couverture n\'a pas été trouvée</string> <string name="cover_image_not_found_content_desc">L\'image de couverture n\'a pas été trouvée</string>
<string name="apply_changes_content_desc">Appliquer les changements</string> <string name="apply_changes_content_desc">Appliquer les changements</string>
@ -275,7 +267,6 @@
<string name="line_height_option">Hauteur de la ligne</string> <string name="line_height_option">Hauteur de la ligne</string>
<string name="dark_theme_on">Activé</string> <string name="dark_theme_on">Activé</string>
<string name="pure_dark_off">Désactivé</string> <string name="pure_dark_off">Désactivé</string>
<string name="files_structure_directory">Répertoires</string>
<string name="browse_sort_order_file_format">Format de fichier</string> <string name="browse_sort_order_file_format">Format de fichier</string>
<string name="browse_sort_order_name">Alphabétiquement</string> <string name="browse_sort_order_name">Alphabétiquement</string>
<string name="move_this_book">Déplacer</string> <string name="move_this_book">Déplacer</string>
@ -300,7 +291,6 @@
<string name="sort_order_content_desc">Ordre de tri</string> <string name="sort_order_content_desc">Ordre de tri</string>
<string name="history_content_desc">Historique de lecture</string> <string name="history_content_desc">Historique de lecture</string>
<string name="today">Aujourd\'hui</string> <string name="today">Aujourd\'hui</string>
<string name="favorite_directory_content_desc">Répertoire favoris</string>
<string name="create_color_preset_content_desc">Créer un nouveau préréglage de couleur</string> <string name="create_color_preset_content_desc">Créer un nouveau préréglage de couleur</string>
<string name="filter_content_desc">Filtre</string> <string name="filter_content_desc">Filtre</string>
<string name="absolute_dark_option">Noir absolu</string> <string name="absolute_dark_option">Noir absolu</string>

View file

@ -138,11 +138,8 @@
<string name="perception_expander_option">धारणा विस्तारक</string> <string name="perception_expander_option">धारणा विस्तारक</string>
<string name="perception_expander_option_desc">केंद्र पर ध्यान केंद्रित करके अपनी पढ़ने की गति बढ़ाएँ</string> <string name="perception_expander_option_desc">केंद्र पर ध्यान केंद्रित करके अपनी पढ़ने की गति बढ़ाएँ</string>
<string name="perception_expander_padding_option">धारणा विस्तारक लाइन पैडिंग</string> <string name="perception_expander_padding_option">धारणा विस्तारक लाइन पैडिंग</string>
<string name="browse_files_structure_option">फ़ाइल संरचना</string>
<string name="browse_layout_option">प्रदर्शन मोड</string> <string name="browse_layout_option">प्रदर्शन मोड</string>
<string name="browse_grid_size_option">ग्रिड का आकार</string> <string name="browse_grid_size_option">ग्रिड का आकार</string>
<string name="browse_pin_favorite_directories_option">पसंदीदा फ़ोल्डर पिन करें</string>
<string name="browse_pin_favorite_directories_option_desc">पसंदीदा फ़ोल्डरों को स्क्रीन के शीर्ष पर पिन करें</string>
<string name="green_color">हरा</string> <string name="green_color">हरा</string>
<string name="blue_color">नीला</string> <string name="blue_color">नीला</string>
<string name="color_preset_placeholder">प्रीसेट को नाम दें…</string> <string name="color_preset_placeholder">प्रीसेट को नाम दें…</string>
@ -157,13 +154,10 @@
<string name="theme_contrast_high">ऊँचा</string> <string name="theme_contrast_high">ऊँचा</string>
<string name="font_style_italic">तिर्छा</string> <string name="font_style_italic">तिर्छा</string>
<string name="font_style_normal">साधारण</string> <string name="font_style_normal">साधारण</string>
<string name="files_structure_all">सभी फाइलें</string>
<string name="files_structure_directory">फ़ोल्डर्स</string>
<string name="browse_layout_list">सूची</string> <string name="browse_layout_list">सूची</string>
<string name="browse_layout_grid">ग्रिड</string> <string name="browse_layout_grid">ग्रिड</string>
<string name="browse_grid_size_auto">स्वचालित</string> <string name="browse_grid_size_auto">स्वचालित</string>
<string name="browse_sort_order_file_format">फाइल का प्रकार</string> <string name="browse_sort_order_file_format">फाइल का प्रकार</string>
<string name="browse_sort_order_file_type">फाइल का प्रकार</string>
<string name="browse_sort_order_last_modified">आखिरी बार संशोधित</string> <string name="browse_sort_order_last_modified">आखिरी बार संशोधित</string>
<string name="alignment_start">प्रारंभ</string> <string name="alignment_start">प्रारंभ</string>
<string name="alignment_justify">सममित करें</string> <string name="alignment_justify">सममित करें</string>
@ -244,7 +238,6 @@
<string name="history_element_deleted">इतिहास तत्व सफलतापूर्वक हटा दिया गया।</string> <string name="history_element_deleted">इतिहास तत्व सफलतापूर्वक हटा दिया गया।</string>
<string name="file_name">फ़ाइल का नाम</string> <string name="file_name">फ़ाइल का नाम</string>
<string name="unknown">अज्ञात</string> <string name="unknown">अज्ञात</string>
<string name="internal_storage">आंतरिक स्टोरेज</string>
<string name="report_bug_option">एक बग रिपोर्ट करो</string> <string name="report_bug_option">एक बग रिपोर्ट करो</string>
<string name="credits_updates">नए अपडेट का प्रबंधन</string> <string name="credits_updates">नए अपडेट का प्रबंधन</string>
<string name="help_desc_how_to_add_books_3">यदि आपको डाउनलोड की गई पुस्तकें दिखाई नहीं देती हैं तो सूची को नीचे खींचकर ताज़ा करने का प्रयास करें। सुनिश्चित करें कि आपकी पुस्तकों में फ़ाइल स्वरूप समर्थित है। फिर पुस्तक को चुनने के लिए उस पर क्लिक करें या उसका स्थान दिखाने के लिए उसे दबाए रखें। अपनी इच्छित सभी पुस्तकों का चयन करने के बाद, ऊपरी दाएं कोने में चेकमार्क आइकन पर क्लिक करें, सभी पुस्तकों के लोड होने की प्रतीक्षा करें और \"जोड़ें\" पर क्लिक करें। अब आपको वे सभी पुस्तकें दिखनी चाहिए जिन्हें आपने इसमें जोड़ा है</string> <string name="help_desc_how_to_add_books_3">यदि आपको डाउनलोड की गई पुस्तकें दिखाई नहीं देती हैं तो सूची को नीचे खींचकर ताज़ा करने का प्रयास करें। सुनिश्चित करें कि आपकी पुस्तकों में फ़ाइल स्वरूप समर्थित है। फिर पुस्तक को चुनने के लिए उस पर क्लिक करें या उसका स्थान दिखाने के लिए उसे दबाए रखें। अपनी इच्छित सभी पुस्तकों का चयन करने के बाद, ऊपरी दाएं कोने में चेकमार्क आइकन पर क्लिक करें, सभी पुस्तकों के लोड होने की प्रतीक्षा करें और \"जोड़ें\" पर क्लिक करें। अब आपको वे सभी पुस्तकें दिखनी चाहिए जिन्हें आपने इसमें जोड़ा है</string>

View file

@ -33,7 +33,6 @@
<string name="browse_content_desc">Aggiungi libri</string> <string name="browse_content_desc">Aggiungi libri</string>
<string name="open_reader_settings_content_desc">Impostazioni lettore</string> <string name="open_reader_settings_content_desc">Impostazioni lettore</string>
<string name="file_icon_content_desc">File</string> <string name="file_icon_content_desc">File</string>
<string name="favorite_directory_content_desc">Cartella preferita</string>
<string name="sort_order_content_desc">Criterio di ordinamento</string> <string name="sort_order_content_desc">Criterio di ordinamento</string>
<string name="github_profile_content_desc">Profilo GitHub</string> <string name="github_profile_content_desc">Profilo GitHub</string>
<string name="browse_grid_size_option">Dimensioni griglia</string> <string name="browse_grid_size_option">Dimensioni griglia</string>
@ -79,7 +78,6 @@
<string name="yes_go_to_help">Sì, vai ad Aiuto</string> <string name="yes_go_to_help">Sì, vai ad Aiuto</string>
<string name="no">No</string> <string name="no">No</string>
<string name="delete_color_preset_content_desc">Elimina preset di colori</string> <string name="delete_color_preset_content_desc">Elimina preset di colori</string>
<string name="files_structure_directory">Cartelle</string>
<string name="pure_dark_on">Abilitato</string> <string name="pure_dark_on">Abilitato</string>
<string name="help_screen">Aiuto</string> <string name="help_screen">Aiuto</string>
<string name="error_content_desc">Errore</string> <string name="error_content_desc">Errore</string>
@ -129,7 +127,6 @@
<string name="theme_contrast_standard">Standard</string> <string name="theme_contrast_standard">Standard</string>
<string name="browse_sort_order_name">Alfabetico</string> <string name="browse_sort_order_name">Alfabetico</string>
<string name="browse_sort_order_last_modified">Ultima modifica</string> <string name="browse_sort_order_last_modified">Ultima modifica</string>
<string name="browse_sort_order_file_type">Tipo file</string>
<string name="browse_sort_order_file_size">Dimensioni file</string> <string name="browse_sort_order_file_size">Dimensioni file</string>
<string name="pink_theme">Saturno</string> <string name="pink_theme">Saturno</string>
<string name="dynamic_theme">Mercurio</string> <string name="dynamic_theme">Mercurio</string>
@ -157,7 +154,6 @@
<string name="author">Autore</string> <string name="author">Autore</string>
<string name="browse_layout_list">Lista</string> <string name="browse_layout_list">Lista</string>
<string name="credits_translation">Traduzione</string> <string name="credits_translation">Traduzione</string>
<string name="directory_icon_content_desc">Cartella</string>
<string name="move_book">Spostare libro?</string> <string name="move_book">Spostare libro?</string>
<string name="settings_screen">Impostazioni</string> <string name="settings_screen">Impostazioni</string>
<string name="add_books">Aggiungere libri?</string> <string name="add_books">Aggiungere libri?</string>
@ -180,14 +176,12 @@
<string name="general_browse_settings">Generale</string> <string name="general_browse_settings">Generale</string>
<string name="filter_browse_settings">Filtro</string> <string name="filter_browse_settings">Filtro</string>
<string name="font_style_normal">Normale</string> <string name="font_style_normal">Normale</string>
<string name="files_structure_all">Tutti i file</string>
<string name="delete_whole_history_content_desc">Elimina tutta la cronologia</string> <string name="delete_whole_history_content_desc">Elimina tutta la cronologia</string>
<string name="yesterday">Ieri</string> <string name="yesterday">Ieri</string>
<string name="random_string">Random</string> <string name="random_string">Random</string>
<string name="screen_orientation_option">Orientamento dello schermo</string> <string name="screen_orientation_option">Orientamento dello schermo</string>
<string name="dark_theme_off">Disabilitato</string> <string name="dark_theme_off">Disabilitato</string>
<string name="screen_orientation_free">Libero</string> <string name="screen_orientation_free">Libero</string>
<string name="browse_files_structure_option">Struttura dei file</string>
<string name="browse_layout_option">Modalità di visualizzazione</string> <string name="browse_layout_option">Modalità di visualizzazione</string>
<string name="reading_speed_reader_settings">Velocità di lettura</string> <string name="reading_speed_reader_settings">Velocità di lettura</string>
<string name="error_no_share_app">Nessuna app da condividere trovata.</string> <string name="error_no_share_app">Nessuna app da condividere trovata.</string>
@ -213,7 +207,6 @@
<string name="no_updates">L\'ultima versione dell\'app è già installata.</string> <string name="no_updates">L\'ultima versione dell\'app è già installata.</string>
<string name="help_desc_how_to_read_book_2">Libreria</string> <string name="help_desc_how_to_read_book_2">Libreria</string>
<string name="start_welcome">Benvenuti in Book\'s Story!</string> <string name="start_welcome">Benvenuti in Book\'s Story!</string>
<string name="path_arrow_icon_content_desc">Freccia del percorso</string>
<string name="browse_grid_size_per_row">per riga</string> <string name="browse_grid_size_per_row">per riga</string>
<string name="history_deleted">La cronologia è stata eliminata correttamente.</string> <string name="history_deleted">La cronologia è stata eliminata correttamente.</string>
<string name="press_again_toast">Premere di nuovo Indietro per uscire</string> <string name="press_again_toast">Premere di nuovo Indietro per uscire</string>
@ -247,7 +240,6 @@
<string name="help_desc_how_to_customize_app_2">Impostazioni</string> <string name="help_desc_how_to_customize_app_2">Impostazioni</string>
<string name="delete_history_element_content_desc">Elimina cronologia elemento</string> <string name="delete_history_element_content_desc">Elimina cronologia elemento</string>
<string name="reading_tab">Lettura</string> <string name="reading_tab">Lettura</string>
<string name="browse_pin_favorite_directories_option">Blocca le directory preferite</string>
<string name="help_title_how_to_read_book">Come si legge un libro?</string> <string name="help_title_how_to_read_book">Come si legge un libro?</string>
<string name="clear_selected_items_content_desc">Cancella gli elementi selezionati</string> <string name="clear_selected_items_content_desc">Cancella gli elementi selezionati</string>
<string name="revert_content_desc">Ripristina</string> <string name="revert_content_desc">Ripristina</string>
@ -330,10 +322,8 @@
<string name="help_desc_how_to_manage_history_3">Cliccando sul pulsante Elimina a destra dell\'elemento cronologia, questo verrà eliminato. La cronologia influisce sull\'ordine dei libri in Libreria, eliminando l\'elemento cronologia si riordinerà anche un libro. L\'ultimo libro aperto è sempre il primo in Libreria e Cronologia.</string> <string name="help_desc_how_to_manage_history_3">Cliccando sul pulsante Elimina a destra dell\'elemento cronologia, questo verrà eliminato. La cronologia influisce sull\'ordine dei libri in Libreria, eliminando l\'elemento cronologia si riordinerà anche un libro. L\'ultimo libro aperto è sempre il primo in Libreria e Cronologia.</string>
<string name="help_title_how_to_use_tooltip">Come si utilizzano i suggerimenti?</string> <string name="help_title_how_to_use_tooltip">Come si utilizzano i suggerimenti?</string>
<string name="help_desc_how_to_use_perception_expander_1">L\'espansore di percezione può aiutarti a leggere più velocemente. Per prima cosa, abilitalo nelle impostazioni del Lettore(vedi: Come personalizzare il Lettore?). Una volta abilitato, appariranno due linee verticali su entrambi i lati del Lettore. Per ottimizzare ulteriormente la velocità di lettura, regola il margine per creare meno spazio attorno al centro. Per utilizzarlo, concentrati sul centro dello schermo mentre consenti alla tua visione periferica di cogliere il testo sui lati. Mentre leggi, mantieni la concentrazione sul centro senza guardare direttamente i lati dopo ogni riga.</string> <string name="help_desc_how_to_use_perception_expander_1">L\'espansore di percezione può aiutarti a leggere più velocemente. Per prima cosa, abilitalo nelle impostazioni del Lettore(vedi: Come personalizzare il Lettore?). Una volta abilitato, appariranno due linee verticali su entrambi i lati del Lettore. Per ottimizzare ulteriormente la velocità di lettura, regola il margine per creare meno spazio attorno al centro. Per utilizzarlo, concentrati sul centro dello schermo mentre consenti alla tua visione periferica di cogliere il testo sui lati. Mentre leggi, mantieni la concentrazione sul centro senza guardare direttamente i lati dopo ogni riga.</string>
<string name="internal_storage">Memoria interna</string>
<string name="cover_reset">L\'immagine di copertina è stata reimpostata correttamente.</string> <string name="cover_reset">L\'immagine di copertina è stata reimpostata correttamente.</string>
<string name="credits_ideas">Idea</string> <string name="credits_ideas">Idea</string>
<string name="browse_pin_favorite_directories_option_desc">Aggiungi le tue directory preferite nella parte superiore dello schermo</string>
<string name="whats_new_option">Cosa c\'è di nuovo</string> <string name="whats_new_option">Cosa c\'è di nuovo</string>
<string name="help_desc_how_to_add_books_3">Se non vedi i libri scaricati, prova ad aggiornare l\'elenco tirandolo verso il basso. Assicurati che i tuoi libri abbiano un formato di file supportato. Quindi fai clic sul libro per selezionarlo o tieni premuto per mostrarne la posizione. Dopo aver selezionato tutti i libri desiderati, fai clic sull\'icona del segno di spunta nell\'angolo in alto a destra, attendi che tutti i libri vengano caricati e fai clic su «Aggiungi». Ora dovresti vedere tutti i libri che hai aggiunto nella</string> <string name="help_desc_how_to_add_books_3">Se non vedi i libri scaricati, prova ad aggiornare l\'elenco tirandolo verso il basso. Assicurati che i tuoi libri abbiano un formato di file supportato. Quindi fai clic sul libro per selezionarlo o tieni premuto per mostrarne la posizione. Dopo aver selezionato tutti i libri desiderati, fai clic sull\'icona del segno di spunta nell\'angolo in alto a destra, attendi che tutti i libri vengano caricati e fai clic su «Aggiungi». Ora dovresti vedere tutti i libri che hai aggiunto nella</string>
<string name="contributors_option">Contributori</string> <string name="contributors_option">Contributori</string>

View file

@ -114,14 +114,11 @@
<string name="fullscreen_option">Pełny ekran</string> <string name="fullscreen_option">Pełny ekran</string>
<string name="keep_screen_on_option">Pozostaw włączony ekran</string> <string name="keep_screen_on_option">Pozostaw włączony ekran</string>
<string name="hide_bars_on_fast_scroll_option">Ukryj paski w szybkim przewijaniu</string> <string name="hide_bars_on_fast_scroll_option">Ukryj paski w szybkim przewijaniu</string>
<string name="browse_files_structure_option">Struktura plików</string>
<string name="browse_pin_favorite_directories_option_desc">Przypnij swoje ulubione katalogi na górze ekranu</string>
<string name="pure_dark_off">Wyłączony</string> <string name="pure_dark_off">Wyłączony</string>
<string name="theme_contrast_medium">Średni</string> <string name="theme_contrast_medium">Średni</string>
<string name="font_style_normal">Normalny</string> <string name="font_style_normal">Normalny</string>
<string name="browse_layout_list">Lista</string> <string name="browse_layout_list">Lista</string>
<string name="browse_sort_order_file_format">Format pliku</string> <string name="browse_sort_order_file_format">Format pliku</string>
<string name="browse_sort_order_file_type">Typ pliku</string>
<string name="browse_sort_order_last_modified">Ostatnio modyfikowany</string> <string name="browse_sort_order_last_modified">Ostatnio modyfikowany</string>
<string name="browse_sort_order_file_size">Rozmiar pliku</string> <string name="browse_sort_order_file_size">Rozmiar pliku</string>
<string name="alignment_start">Start</string> <string name="alignment_start">Start</string>
@ -132,7 +129,6 @@
<string name="press_again_toast">Naciśnij ponownie, aby wyjść</string> <string name="press_again_toast">Naciśnij ponownie, aby wyjść</string>
<string name="fast_color_preset_change_option_desc">Przesuń w lewo lub w prawo, aby zmienić ustawienie koloru</string> <string name="fast_color_preset_change_option_desc">Przesuń w lewo lub w prawo, aby zmienić ustawienie koloru</string>
<string name="error_could_not_get_text">Treść książki jest pusta. Upewnij się, że zawartość książki nie jest pusta i zaktualizuj ją.</string> <string name="error_could_not_get_text">Treść książki jest pusta. Upewnij się, że zawartość książki nie jest pusta i zaktualizuj ją.</string>
<string name="files_structure_directory">Katalogi</string>
<string name="error_no_translator">Nie znaleziono aplikacji tłumacza.</string> <string name="error_no_translator">Nie znaleziono aplikacji tłumacza.</string>
<string name="update_app_description">Znaleziono nową wersję Book\'s Story. Chcesz ją pobrać? Klikając przycisk « Pobierz », zostaniesz przeniesiony do przeglądarki i automatycznie pobierzesz najnowszą aktualizację.</string> <string name="update_app_description">Znaleziono nową wersję Book\'s Story. Chcesz ją pobrać? Klikając przycisk « Pobierz », zostaniesz przeniesiony do przeglądarki i automatycznie pobierzesz najnowszą aktualizację.</string>
<string name="browse_layout_grid">Siatka</string> <string name="browse_layout_grid">Siatka</string>
@ -140,13 +136,11 @@
<string name="reset_cover">Zresetuj obraz okładki</string> <string name="reset_cover">Zresetuj obraz okładki</string>
<string name="move_books">Przenieść książki?</string> <string name="move_books">Przenieść książki?</string>
<string name="error_could_not_reset_cover">Nie można zresetować obrazu okładki.</string> <string name="error_could_not_reset_cover">Nie można zresetować obrazu okładki.</string>
<string name="browse_pin_favorite_directories_option">Przypnij ulubione katalogi</string>
<string name="delete_books_description">To spowoduje usunięcie wszystkie wybranych książek (%1$s) z bazy danych. Nie usunie wybranych książek z twojego urządzenia.</string> <string name="delete_books_description">To spowoduje usunięcie wszystkie wybranych książek (%1$s) z bazy danych. Nie usunie wybranych książek z twojego urządzenia.</string>
<string name="browse_grid_size_per_row">na rząd</string> <string name="browse_grid_size_per_row">na rząd</string>
<string name="text_alignment_option">Wyrównanie tekstu</string> <string name="text_alignment_option">Wyrównanie tekstu</string>
<string name="dropped_tab">Porzucone</string> <string name="dropped_tab">Porzucone</string>
<string name="browse_layout_option">Tryb wyświetlania</string> <string name="browse_layout_option">Tryb wyświetlania</string>
<string name="files_structure_all">Wszystkie pliki</string>
<string name="add_books_description">Możesz wybrać książki, które chcesz dodać. Możesz później edytować tytuł i obraz okładki książki. Proces ładowania może potrwać do kilku minut.</string> <string name="add_books_description">Możesz wybrać książki, które chcesz dodać. Możesz później edytować tytuł i obraz okładki książki. Proces ładowania może potrwać do kilku minut.</string>
<string name="storage_permission_description">Potrzebujemy uprawnień do przechowywania, aby przeskanować Twoje urządzenie w poszukiwaniu książek. Bez tego pozwolenia nie będziesz mógł dodać książki.</string> <string name="storage_permission_description">Potrzebujemy uprawnień do przechowywania, aby przeskanować Twoje urządzenie w poszukiwaniu książek. Bez tego pozwolenia nie będziesz mógł dodać książki.</string>
<string name="error_no_browser">Nie znaleziono aplikacji przeglądarki.</string> <string name="error_no_browser">Nie znaleziono aplikacji przeglądarki.</string>
@ -217,7 +211,6 @@
<string name="file_last_opened">Plik ostatnio otwarty</string> <string name="file_last_opened">Plik ostatnio otwarty</string>
<string name="file_size">Rozmiar pliku</string> <string name="file_size">Rozmiar pliku</string>
<string name="unknown">Nieznany</string> <string name="unknown">Nieznany</string>
<string name="internal_storage">Pamięć wewnętrzna</string>
<string name="credits_icon">Ikony</string> <string name="credits_icon">Ikony</string>
<string name="move_books_content_desc">Przenieś wybrane książki</string> <string name="move_books_content_desc">Przenieś wybrane książki</string>
<string name="revert_content_desc">Przywróć</string> <string name="revert_content_desc">Przywróć</string>
@ -241,8 +234,6 @@
<string name="go_back_content_desc">Wróć</string> <string name="go_back_content_desc">Wróć</string>
<string name="cover_image_content_desc">Obraz okładki</string> <string name="cover_image_content_desc">Obraz okładki</string>
<string name="open_reader_settings_content_desc">Ustawienia czytnika</string> <string name="open_reader_settings_content_desc">Ustawienia czytnika</string>
<string name="favorite_directory_content_desc">Ulubiony katalog</string>
<string name="path_arrow_icon_content_desc">Strzałka ścieżki</string>
<string name="checkbox_content_desc">Pole wyboru</string> <string name="checkbox_content_desc">Pole wyboru</string>
<string name="add_files_content_desc">Dodaj pliki</string> <string name="add_files_content_desc">Dodaj pliki</string>
<string name="delete_history_element_content_desc">Usuń element historii</string> <string name="delete_history_element_content_desc">Usuń element historii</string>
@ -298,7 +289,6 @@
<string name="whats_new_option">Co nowego</string> <string name="whats_new_option">Co nowego</string>
<string name="licenses_option">Licencje open source</string> <string name="licenses_option">Licencje open source</string>
<string name="help_desc_how_to_customize_reader_2">Ustawienia</string> <string name="help_desc_how_to_customize_reader_2">Ustawienia</string>
<string name="directory_icon_content_desc">Katalog</string>
<string name="error_content_desc">Błąd</string> <string name="error_content_desc">Błąd</string>
<string name="search_content_desc">Szukaj</string> <string name="search_content_desc">Szukaj</string>
<string name="clear_selected_items_content_desc">Wyczyść wybrane elementy</string> <string name="clear_selected_items_content_desc">Wyczyść wybrane elementy</string>

View file

@ -73,7 +73,6 @@
<string name="dark_theme_follow_system">Sistema</string> <string name="dark_theme_follow_system">Sistema</string>
<string name="theme_contrast_standard">Padrão</string> <string name="theme_contrast_standard">Padrão</string>
<string name="font_style_normal">Normal</string> <string name="font_style_normal">Normal</string>
<string name="files_structure_directory">Diretórios</string>
<string name="storage_permission">Dar permissão?</string> <string name="storage_permission">Dar permissão?</string>
<string name="delete_history">Apagar histórico de leitura?</string> <string name="delete_history">Apagar histórico de leitura?</string>
<string name="author">Autor</string> <string name="author">Autor</string>
@ -111,7 +110,6 @@
<string name="yesterday">Ontem</string> <string name="yesterday">Ontem</string>
<string name="checkbox_content_desc">Checkbox</string> <string name="checkbox_content_desc">Checkbox</string>
<string name="file_icon_content_desc">Arquivo</string> <string name="file_icon_content_desc">Arquivo</string>
<string name="directory_icon_content_desc">Diretório</string>
<string name="error_content_desc">Erro</string> <string name="error_content_desc">Erro</string>
<string name="search_content_desc">Pesquisar</string> <string name="search_content_desc">Pesquisar</string>
<string name="start_permissions_preferences">Permissões</string> <string name="start_permissions_preferences">Permissões</string>
@ -156,7 +154,6 @@
<string name="font_color_option">Cor da fonte</string> <string name="font_color_option">Cor da fonte</string>
<string name="vertical_padding_option">Margens verticais</string> <string name="vertical_padding_option">Margens verticais</string>
<string name="text_alignment_option">Alinhamento do texto</string> <string name="text_alignment_option">Alinhamento do texto</string>
<string name="files_structure_all">Todos os arquivos</string>
<string name="file_size">Tamanho do arquivo</string> <string name="file_size">Tamanho do arquivo</string>
<string name="contributors_option">Contribuidores</string> <string name="contributors_option">Contribuidores</string>
<string name="app_theme_option">Tema do aplicativo</string> <string name="app_theme_option">Tema do aplicativo</string>
@ -170,10 +167,8 @@
<string name="paragraph_height_option">Altura do parágrafo</string> <string name="paragraph_height_option">Altura do parágrafo</string>
<string name="color_preset_option">Padrão de cores</string> <string name="color_preset_option">Padrão de cores</string>
<string name="cutout_padding_option">Margem do recorte</string> <string name="cutout_padding_option">Margem do recorte</string>
<string name="browse_files_structure_option">Estrutura dos arquivos</string>
<string name="browse_layout_option">Modo de exibição</string> <string name="browse_layout_option">Modo de exibição</string>
<string name="browse_grid_size_per_row">por linha</string> <string name="browse_grid_size_per_row">por linha</string>
<string name="browse_sort_order_file_type">Tipo de arquivo</string>
<string name="already_read_tab">Lido</string> <string name="already_read_tab">Lido</string>
<string name="browse_grid_size_option">Tamanho da grade</string> <string name="browse_grid_size_option">Tamanho da grade</string>
<string name="grant_permission">Dar permissão</string> <string name="grant_permission">Dar permissão</string>
@ -184,7 +179,6 @@
<string name="error_closed_source">Código fechado</string> <string name="error_closed_source">Código fechado</string>
<string name="web_search">Pesquisa web</string> <string name="web_search">Pesquisa web</string>
<string name="side_padding_option">Margens laterais</string> <string name="side_padding_option">Margens laterais</string>
<string name="internal_storage">Armazenamento interno</string>
<string name="screen_brightness_option">Iluminação</string> <string name="screen_brightness_option">Iluminação</string>
<string name="browse_sort_order_file_format">Formato de arquivo</string> <string name="browse_sort_order_file_format">Formato de arquivo</string>
<string name="browse_sort_order_last_modified">Modificação mais recente</string> <string name="browse_sort_order_last_modified">Modificação mais recente</string>
@ -210,7 +204,6 @@
<string name="start_done">Está tudo feito!</string> <string name="start_done">Está tudo feito!</string>
<string name="cover_image_content_desc">Imagem da capa</string> <string name="cover_image_content_desc">Imagem da capa</string>
<string name="open_reader_settings_content_desc">Configurações do leitor</string> <string name="open_reader_settings_content_desc">Configurações do leitor</string>
<string name="favorite_directory_content_desc">Diretório favorito</string>
<string name="slava_ukraini">Slava Ukraini!</string> <string name="slava_ukraini">Slava Ukraini!</string>
<string name="exit_search_content_desc">Fechar pesquisa</string> <string name="exit_search_content_desc">Fechar pesquisa</string>
<string name="app_icon_content_desc">Ícone do App</string> <string name="app_icon_content_desc">Ícone do App</string>

View file

@ -42,7 +42,6 @@
<string name="dark_theme_off">முடக்கப்பட்டது</string> <string name="dark_theme_off">முடக்கப்பட்டது</string>
<string name="dark_theme_on">இயக்கப்பட்டது</string> <string name="dark_theme_on">இயக்கப்பட்டது</string>
<string name="dark_theme_follow_system">மண்டலம்</string> <string name="dark_theme_follow_system">மண்டலம்</string>
<string name="files_structure_all">அனைத்து கோப்புகள்</string>
<string name="lavender_theme">எரிச்</string> <string name="lavender_theme">எரிச்</string>
<string name="books_moved">தேர்ந்தெடுக்கப்பட்ட அனைத்து புத்தகங்களும் வெற்றிகரமாக நகர்த்தப்பட்டன.</string> <string name="books_moved">தேர்ந்தெடுக்கப்பட்ட அனைத்து புத்தகங்களும் வெற்றிகரமாக நகர்த்தப்பட்டன.</string>
<string name="books_deleted">தேர்ந்தெடுக்கப்பட்ட அனைத்து புத்தகங்களும் வெற்றிகரமாக நீக்கப்பட்டன.</string> <string name="books_deleted">தேர்ந்தெடுக்கப்பட்ட அனைத்து புத்தகங்களும் வெற்றிகரமாக நீக்கப்பட்டன.</string>
@ -65,7 +64,6 @@
<string name="go_back_content_desc">திரும்பிச் செல்லுங்கள்</string> <string name="go_back_content_desc">திரும்பிச் செல்லுங்கள்</string>
<string name="cover_image_content_desc">கவர் படம்</string> <string name="cover_image_content_desc">கவர் படம்</string>
<string name="open_reader_settings_content_desc">வாசகர் அமைப்புகள்</string> <string name="open_reader_settings_content_desc">வாசகர் அமைப்புகள்</string>
<string name="path_arrow_icon_content_desc">பாதை அம்பு</string>
<string name="checkbox_content_desc">தேர்வுப்பெட்டி</string> <string name="checkbox_content_desc">தேர்வுப்பெட்டி</string>
<string name="library_content_desc">உங்கள் நூலகம்</string> <string name="library_content_desc">உங்கள் நூலகம்</string>
<string name="delete_history_element_content_desc">வரலாற்று உறுப்பை நீக்கு</string> <string name="delete_history_element_content_desc">வரலாற்று உறுப்பை நீக்கு</string>
@ -94,7 +92,6 @@
<string name="licenses_option">திறந்த மூல உரிமங்கள்</string> <string name="licenses_option">திறந்த மூல உரிமங்கள்</string>
<string name="help_desc_how_to_manage_history_2">வரலாறு</string> <string name="help_desc_how_to_manage_history_2">வரலாறு</string>
<string name="file_icon_content_desc">கோப்பு</string> <string name="file_icon_content_desc">கோப்பு</string>
<string name="directory_icon_content_desc">அடைவு</string>
<string name="select_all_files_content_desc">எல்லா கோப்புகளையும் தேர்ந்தெடுக்கவும்</string> <string name="select_all_files_content_desc">எல்லா கோப்புகளையும் தேர்ந்தெடுக்கவும்</string>
<string name="exit_search_content_desc">வெளியேறும் தேடல்</string> <string name="exit_search_content_desc">வெளியேறும் தேடல்</string>
<string name="unknown_author">தெரியவில்லை</string> <string name="unknown_author">தெரியவில்லை</string>
@ -246,10 +243,7 @@
<string name="fast_color_preset_change_option_desc">வண்ண முன்னமைவை மாற்ற மேல் பட்டியை இடது அல்லது வலதுபுறமாக ச்வைப் செய்யவும்</string> <string name="fast_color_preset_change_option_desc">வண்ண முன்னமைவை மாற்ற மேல் பட்டியை இடது அல்லது வலதுபுறமாக ச்வைப் செய்யவும்</string>
<string name="letter_spacing_option">கடிதம் இடைவெளி</string> <string name="letter_spacing_option">கடிதம் இடைவெளி</string>
<string name="screen_orientation_option">திரை நோக்குநிலை</string> <string name="screen_orientation_option">திரை நோக்குநிலை</string>
<string name="browse_files_structure_option">கோப்புகள் அமைப்பு</string>
<string name="browse_grid_size_option">கட்டம் அளவு</string> <string name="browse_grid_size_option">கட்டம் அளவு</string>
<string name="browse_pin_favorite_directories_option">பிடித்த கோப்பகங்கள்</string>
<string name="browse_pin_favorite_directories_option_desc">உங்களுக்கு பிடித்த கோப்பகங்களை திரையின் மேற்புறத்தில் பொருத்துங்கள்</string>
<string name="red_color">சிவப்பு</string> <string name="red_color">சிவப்பு</string>
<string name="green_color">பச்சை</string> <string name="green_color">பச்சை</string>
<string name="blue_color">நீலம்</string> <string name="blue_color">நீலம்</string>
@ -258,9 +252,7 @@
<string name="theme_contrast_high">உயர்ந்த</string> <string name="theme_contrast_high">உயர்ந்த</string>
<string name="font_style_italic">சாய்வு</string> <string name="font_style_italic">சாய்வு</string>
<string name="font_style_normal">சாதாரண</string> <string name="font_style_normal">சாதாரண</string>
<string name="files_structure_directory">கோப்பகங்கள்</string>
<string name="browse_sort_order_name">அகரவரிசை</string> <string name="browse_sort_order_name">அகரவரிசை</string>
<string name="browse_sort_order_file_type">கோப்பு வகை</string>
<string name="browse_sort_order_last_modified">கடைசியாக மாற்றப்பட்டது</string> <string name="browse_sort_order_last_modified">கடைசியாக மாற்றப்பட்டது</string>
<string name="browse_sort_order_file_size">கோப்பு அளவு</string> <string name="browse_sort_order_file_size">கோப்பு அளவு</string>
<string name="alignment_start">தொடங்கு</string> <string name="alignment_start">தொடங்கு</string>
@ -288,7 +280,6 @@
<string name="file_path">கோப்பு பாதை</string> <string name="file_path">கோப்பு பாதை</string>
<string name="file_last_opened">கோப்பு கடைசியாக திறக்கப்பட்டது</string> <string name="file_last_opened">கோப்பு கடைசியாக திறக்கப்பட்டது</string>
<string name="file_size">கோப்பு அளவு</string> <string name="file_size">கோப்பு அளவு</string>
<string name="internal_storage">உள் சேமிப்பு</string>
<string name="no_chapters">அத்தியாயங்கள் இல்லை</string> <string name="no_chapters">அத்தியாயங்கள் இல்லை</string>
<string name="chapters">பாடங்கள்</string> <string name="chapters">பாடங்கள்</string>
<string name="app_version_option_desc_1">புத்தகத்தின் கதை v%1$s</string> <string name="app_version_option_desc_1">புத்தகத்தின் கதை v%1$s</string>
@ -330,7 +321,6 @@
<string name="start_done_desc">பயன்பாட்டின் அடிப்படை அமைப்பை நீங்கள் வெற்றிகரமாக முடித்துவிட்டீர்கள். உதவித் திரையைப் படிப்பதன் மூலம் பயன்பாட்டை எவ்வாறு பயன்படுத்துவது என்பதை அறிய விரும்புகிறீர்களா?</string> <string name="start_done_desc">பயன்பாட்டின் அடிப்படை அமைப்பை நீங்கள் வெற்றிகரமாக முடித்துவிட்டீர்கள். உதவித் திரையைப் படிப்பதன் மூலம் பயன்பாட்டை எவ்வாறு பயன்படுத்துவது என்பதை அறிய விரும்புகிறீர்களா?</string>
<string name="yesterday">நேற்று</string> <string name="yesterday">நேற்று</string>
<string name="continue_reading_content_desc">தொடர்ந்து படிக்கவும்</string> <string name="continue_reading_content_desc">தொடர்ந்து படிக்கவும்</string>
<string name="favorite_directory_content_desc">பிடித்த அடைவு</string>
<string name="sort_order_content_desc">வரிசைப்படுத்தும் முறை</string> <string name="sort_order_content_desc">வரிசைப்படுத்தும் முறை</string>
<string name="cover_image_not_found_content_desc">கவர் படம் கிடைக்கவில்லை</string> <string name="cover_image_not_found_content_desc">கவர் படம் கிடைக்கவில்லை</string>
<string name="apply_changes_content_desc">மாற்றங்களைப் பயன்படுத்துங்கள்</string> <string name="apply_changes_content_desc">மாற்றங்களைப் பயன்படுத்துங்கள்</string>

View file

@ -129,11 +129,8 @@
<string name="fast_color_preset_change_option_desc">Renk ön ayarını değiştirmek için üst çubuğu sola veya sağa kaydırın</string> <string name="fast_color_preset_change_option_desc">Renk ön ayarını değiştirmek için üst çubuğu sola veya sağa kaydırın</string>
<string name="text_alignment_option">Metin hizalama</string> <string name="text_alignment_option">Metin hizalama</string>
<string name="letter_spacing_option">Harf aralığı</string> <string name="letter_spacing_option">Harf aralığı</string>
<string name="browse_files_structure_option">Dosya yapısı</string>
<string name="browse_layout_option">Görüntüleme modu</string> <string name="browse_layout_option">Görüntüleme modu</string>
<string name="browse_grid_size_option">Izgara boyutu</string> <string name="browse_grid_size_option">Izgara boyutu</string>
<string name="browse_pin_favorite_directories_option">Favori dizinleri sabitle</string>
<string name="browse_pin_favorite_directories_option_desc">Favori dizinlerinizi ekranın üst kısmına sabitleyin</string>
<string name="red_color">Kırmızı</string> <string name="red_color">Kırmızı</string>
<string name="green_color">Yeşil</string> <string name="green_color">Yeşil</string>
<string name="blue_color">Mavi</string> <string name="blue_color">Mavi</string>
@ -149,15 +146,12 @@
<string name="theme_contrast_high">Yüksek</string> <string name="theme_contrast_high">Yüksek</string>
<string name="font_style_italic">İtalik</string> <string name="font_style_italic">İtalik</string>
<string name="font_style_normal">Normal</string> <string name="font_style_normal">Normal</string>
<string name="files_structure_all">Tüm dosyalar</string>
<string name="files_structure_directory">Dizinler</string>
<string name="browse_layout_list">Liste</string> <string name="browse_layout_list">Liste</string>
<string name="browse_layout_grid">Izgara</string> <string name="browse_layout_grid">Izgara</string>
<string name="browse_grid_size_auto">Otomatik</string> <string name="browse_grid_size_auto">Otomatik</string>
<string name="browse_grid_size_per_row">satır başına</string> <string name="browse_grid_size_per_row">satır başına</string>
<string name="browse_sort_order_name">Alfabetik</string> <string name="browse_sort_order_name">Alfabetik</string>
<string name="browse_sort_order_file_format">Dosya formatı</string> <string name="browse_sort_order_file_format">Dosya formatı</string>
<string name="browse_sort_order_file_type">Dosya türü</string>
<string name="browse_sort_order_last_modified">Son değiştirilme</string> <string name="browse_sort_order_last_modified">Son değiştirilme</string>
<string name="browse_sort_order_file_size">Dosya boyutu</string> <string name="browse_sort_order_file_size">Dosya boyutu</string>
<string name="alignment_start">Başlangıç</string> <string name="alignment_start">Başlangıç</string>
@ -195,7 +189,6 @@
<string name="file_last_opened">Son açılma tarihi</string> <string name="file_last_opened">Son açılma tarihi</string>
<string name="file_size">Dosya boyutu</string> <string name="file_size">Dosya boyutu</string>
<string name="unknown">Bilinmiyor</string> <string name="unknown">Bilinmiyor</string>
<string name="internal_storage">Dahili Depolama</string>
<string name="app_version_option">Uygulama sürümü</string> <string name="app_version_option">Uygulama sürümü</string>
<string name="app_version_option_desc_1">Book Story v%1$s</string> <string name="app_version_option_desc_1">Book Story v%1$s</string>
<string name="app_version_option_desc_2">Güncellemeleri kontrol etmek için tıklayın</string> <string name="app_version_option_desc_2">Güncellemeleri kontrol etmek için tıklayın</string>
@ -268,10 +261,7 @@
<string name="cover_image_content_desc">Kapak resmi</string> <string name="cover_image_content_desc">Kapak resmi</string>
<string name="open_reader_settings_content_desc">Okuyucu ayarları</string> <string name="open_reader_settings_content_desc">Okuyucu ayarları</string>
<string name="file_icon_content_desc">Dosya</string> <string name="file_icon_content_desc">Dosya</string>
<string name="directory_icon_content_desc">Dizin</string>
<string name="favorite_directory_content_desc">Favori dizin</string>
<string name="sort_order_content_desc">Sıralama düzeni</string> <string name="sort_order_content_desc">Sıralama düzeni</string>
<string name="path_arrow_icon_content_desc">Yol oku</string>
<string name="checkbox_content_desc">Onay kutusu</string> <string name="checkbox_content_desc">Onay kutusu</string>
<string name="cover_image_not_found_content_desc">Kapak resmi bulunamadı</string> <string name="cover_image_not_found_content_desc">Kapak resmi bulunamadı</string>
<string name="apply_changes_content_desc">Değişiklikleri uygula</string> <string name="apply_changes_content_desc">Değişiklikleri uygula</string>

View file

@ -209,12 +209,8 @@
<string name="progress_bar_font_size_option">Розмір шрифта</string> <string name="progress_bar_font_size_option">Розмір шрифта</string>
<!-- Browse --> <!-- Browse -->
<string name="browse_files_structure_option">Структура файлів</string>
<string name="browse_layout_option">Режим відображення</string> <string name="browse_layout_option">Режим відображення</string>
<string name="browse_grid_size_option">Кількість комірок</string> <string name="browse_grid_size_option">Кількість комірок</string>
<string name="browse_pin_favorite_directories_option">Закріпити улюблені директорії</string>
<string name="browse_pin_favorite_directories_option_desc">Закріпіть ваші улюблені директорії зверху екрана</string>
<!-- Color presets --> <!-- Color presets -->
<string name="red_color">Червоний</string> <string name="red_color">Червоний</string>
<string name="green_color">Зелений</string> <string name="green_color">Зелений</string>
@ -241,9 +237,6 @@
<string name="font_style_normal">Нормальний</string> <string name="font_style_normal">Нормальний</string>
<!-- Files Structure properties --> <!-- Files Structure properties -->
<string name="files_structure_all">Всі файли</string>
<string name="files_structure_directory">Директорії</string>
<!-- Browse Layout properties --> <!-- Browse Layout properties -->
<string name="browse_layout_list">Список</string> <string name="browse_layout_list">Список</string>
<string name="browse_layout_grid">Сітка</string> <string name="browse_layout_grid">Сітка</string>
@ -255,7 +248,6 @@
<!-- Browse Sort Order properties --> <!-- Browse Sort Order properties -->
<string name="browse_sort_order_name">За алфавітом</string> <string name="browse_sort_order_name">За алфавітом</string>
<string name="browse_sort_order_file_format">Формат файла</string> <string name="browse_sort_order_file_format">Формат файла</string>
<string name="browse_sort_order_file_type">Тип файла</string>
<string name="browse_sort_order_last_modified">Остання зміна</string> <string name="browse_sort_order_last_modified">Остання зміна</string>
<string name="browse_sort_order_file_size">Розмір файла</string> <string name="browse_sort_order_file_size">Розмір файла</string>
@ -334,8 +326,6 @@
<string name="unknown">Невідомо</string> <string name="unknown">Невідомо</string>
<!-- Browse --> <!-- Browse -->
<string name="internal_storage">Внутрішнє Сховище</string>
<!-- Reader --> <!-- Reader -->
<string name="no_chapters">Немає розділів</string> <string name="no_chapters">Немає розділів</string>
<string name="chapters">Розділи</string> <string name="chapters">Розділи</string>
@ -437,10 +427,7 @@
<string name="cover_image_content_desc">Обкладинка</string> <string name="cover_image_content_desc">Обкладинка</string>
<string name="open_reader_settings_content_desc">Налаштування читача</string> <string name="open_reader_settings_content_desc">Налаштування читача</string>
<string name="file_icon_content_desc">Файл</string> <string name="file_icon_content_desc">Файл</string>
<string name="directory_icon_content_desc">Тека</string>
<string name="favorite_directory_content_desc">Улюблена тека</string>
<string name="sort_order_content_desc">Порядок сортування</string> <string name="sort_order_content_desc">Порядок сортування</string>
<string name="path_arrow_icon_content_desc">Стрілка шляху</string>
<string name="checkbox_content_desc">Галочка</string> <string name="checkbox_content_desc">Галочка</string>
<string name="cover_image_not_found_content_desc">Обкладенка не знайдена</string> <string name="cover_image_not_found_content_desc">Обкладенка не знайдена</string>
<string name="apply_changes_content_desc">Застосувати зміни</string> <string name="apply_changes_content_desc">Застосувати зміни</string>

View file

@ -87,8 +87,6 @@
<string name="absolute_dark_option_desc">改变背景颜色使完全黑暗</string> <string name="absolute_dark_option_desc">改变背景颜色使完全黑暗</string>
<string name="cutout_padding_option">镂空填充</string> <string name="cutout_padding_option">镂空填充</string>
<string name="cutout_padding_option_desc">将填充应用于镂空区域</string> <string name="cutout_padding_option_desc">将填充应用于镂空区域</string>
<string name="browse_pin_favorite_directories_option_desc">在屏幕顶端固定您的收藏目录</string>
<string name="browse_pin_favorite_directories_option">固定收藏目录</string>
<string name="browse_grid_size_option">网格大小</string> <string name="browse_grid_size_option">网格大小</string>
<string name="dark_theme_follow_system">系统</string> <string name="dark_theme_follow_system">系统</string>
<string name="font_style_normal">正常</string> <string name="font_style_normal">正常</string>
@ -155,7 +153,6 @@
<string name="perception_expander_option">感知扩展器</string> <string name="perception_expander_option">感知扩展器</string>
<string name="perception_expander_option_desc">专注于中心以提升你的阅读速度</string> <string name="perception_expander_option_desc">专注于中心以提升你的阅读速度</string>
<string name="perception_expander_thickness_option">感知扩展器行厚度</string> <string name="perception_expander_thickness_option">感知扩展器行厚度</string>
<string name="browse_files_structure_option">文件结构</string>
<string name="green_color">绿色</string> <string name="green_color">绿色</string>
<string name="general_browse_settings">常规</string> <string name="general_browse_settings">常规</string>
<string name="theme_contrast_medium">中等</string> <string name="theme_contrast_medium">中等</string>
@ -187,10 +184,8 @@
<string name="alignment_center">居中</string> <string name="alignment_center">居中</string>
<string name="dynamic_theme">水星</string> <string name="dynamic_theme">水星</string>
<string name="lavender_theme">阋神星</string> <string name="lavender_theme">阋神星</string>
<string name="files_structure_directory">目录</string>
<string name="browse_sort_order_file_size">文件大小</string> <string name="browse_sort_order_file_size">文件大小</string>
<string name="browse_sort_order_last_modified">最后修改</string> <string name="browse_sort_order_last_modified">最后修改</string>
<string name="files_structure_all">全部文件</string>
<string name="general_tab">常规</string> <string name="general_tab">常规</string>
<string name="reader_tab">阅读器</string> <string name="reader_tab">阅读器</string>
<string name="general_settings">常规</string> <string name="general_settings">常规</string>
@ -198,7 +193,6 @@
<string name="read_keep">继续坚持!</string> <string name="read_keep">继续坚持!</string>
<string name="browse_layout_grid">网格</string> <string name="browse_layout_grid">网格</string>
<string name="browse_grid_size_auto">自动</string> <string name="browse_grid_size_auto">自动</string>
<string name="browse_sort_order_file_type">文件类型</string>
<string name="books_added">成功添加所有已选择的书。</string> <string name="books_added">成功添加所有已选择的书。</string>
<string name="books_deleted">成功删除所有已选择的书。</string> <string name="books_deleted">成功删除所有已选择的书。</string>
<string name="cover_image_deleted">成功删除了封面图片。</string> <string name="cover_image_deleted">成功删除了封面图片。</string>
@ -234,7 +228,6 @@
<string name="slava_ukraini">荣耀属于乌克兰!</string> <string name="slava_ukraini">荣耀属于乌克兰!</string>
<string name="file_last_opened">文件最后打开</string> <string name="file_last_opened">文件最后打开</string>
<string name="unknown">未知</string> <string name="unknown">未知</string>
<string name="internal_storage">内部存储</string>
<string name="help_translate_option">帮助翻译</string> <string name="help_translate_option">帮助翻译</string>
<string name="credits_translation">翻译</string> <string name="credits_translation">翻译</string>
<string name="help_desc_how_to_add_books_3">如果你没有看见已下载的书可以尝试下拉刷新列表。确保你的书拥有所支持的文件格式。点击书来选择它或者按住来显示它的位置。当你选择了所有想选择的书之后,点击右上角的对勾图标,等待所有的书加载好后点击“添加”。所有你已经添加的书都应该显示在</string> <string name="help_desc_how_to_add_books_3">如果你没有看见已下载的书可以尝试下拉刷新列表。确保你的书拥有所支持的文件格式。点击书来选择它或者按住来显示它的位置。当你选择了所有想选择的书之后,点击右上角的对勾图标,等待所有的书加载好后点击“添加”。所有你已经添加的书都应该显示在</string>
@ -286,7 +279,6 @@
<string name="start_welcome">欢迎来到“Book\'s Story”</string> <string name="start_welcome">欢迎来到“Book\'s Story”</string>
<string name="help_desc_how_to_use_perception_expander_1">Perception Expander可以帮助你加快阅读速度。 首先,在阅读器设置中启用它(请参阅:如何自定义阅读器?) 启用后,阅读器两侧会出现两条竖线。 要进一步优化阅读速度,可以调整边距以减少屏幕四周的空间。 要使用它,请将注意力集中在屏幕中央,同时让你的余光捕捉到两侧的文字。 阅读时,请将注意力集中在中心位置,不要在每一行之后直接看两侧</string> <string name="help_desc_how_to_use_perception_expander_1">Perception Expander可以帮助你加快阅读速度。 首先,在阅读器设置中启用它(请参阅:如何自定义阅读器?) 启用后,阅读器两侧会出现两条竖线。 要进一步优化阅读速度,可以调整边距以减少屏幕四周的空间。 要使用它,请将注意力集中在屏幕中央,同时让你的余光捕捉到两侧的文字。 阅读时,请将注意力集中在中心位置,不要在每一行之后直接看两侧</string>
<string name="reading_mode_reader_settings">阅读模式</string> <string name="reading_mode_reader_settings">阅读模式</string>
<string name="directory_icon_content_desc">阅读器设置</string>
<string name="today">今天</string> <string name="today">今天</string>
<string name="yesterday">昨天</string> <string name="yesterday">昨天</string>
<string name="continue_reading_content_desc">继续阅读</string> <string name="continue_reading_content_desc">继续阅读</string>
@ -302,7 +294,6 @@
<string name="start_permissions_notifications_desc">用于检查应用更新</string> <string name="start_permissions_notifications_desc">用于检查应用更新</string>
<string name="start_language_preferences">语言偏好</string> <string name="start_language_preferences">语言偏好</string>
<string name="start_theme_preferences">应用主题</string> <string name="start_theme_preferences">应用主题</string>
<string name="favorite_directory_content_desc">词典偏好</string>
<string name="sort_order_content_desc">排序规则</string> <string name="sort_order_content_desc">排序规则</string>
<string name="apply_changes_content_desc">应用更改</string> <string name="apply_changes_content_desc">应用更改</string>
<string name="search_content_desc">搜索</string> <string name="search_content_desc">搜索</string>
@ -320,7 +311,6 @@
<string name="move_books_content_desc">移动所选书籍</string> <string name="move_books_content_desc">移动所选书籍</string>
<string name="go_back_content_desc">返回</string> <string name="go_back_content_desc">返回</string>
<string name="open_reader_settings_content_desc">阅读设置</string> <string name="open_reader_settings_content_desc">阅读设置</string>
<string name="path_arrow_icon_content_desc">路径箭头</string>
<string name="delete_color_preset_content_desc">删除颜色预设</string> <string name="delete_color_preset_content_desc">删除颜色预设</string>
<string name="checkpoint_back_content_desc">检查点撤回</string> <string name="checkpoint_back_content_desc">检查点撤回</string>
<string name="library_content_desc">你的书库</string> <string name="library_content_desc">你的书库</string>

View file

@ -266,13 +266,8 @@
<string name="progress_bar_font_size_option">Font size</string> <string name="progress_bar_font_size_option">Font size</string>
<!-- Browse --> <!-- Browse -->
<string name="browse_files_structure_option">Files structure</string>
<string name="browse_layout_option">Display mode</string> <string name="browse_layout_option">Display mode</string>
<string name="browse_grid_size_option">Grid size</string> <string name="browse_grid_size_option">Grid size</string>
<string name="browse_pin_favorite_directories_option">Pin favorite directories</string>
<string name="browse_pin_favorite_directories_option_desc">
Pin your favorite directories to the top of the screen
</string>
<!-- Color presets --> <!-- Color presets -->
<string name="red_color">Red</string> <string name="red_color">Red</string>
@ -299,10 +294,6 @@
<string name="font_style_italic">Italic</string> <string name="font_style_italic">Italic</string>
<string name="font_style_normal">Normal</string> <string name="font_style_normal">Normal</string>
<!-- Files Structure properties -->
<string name="files_structure_all">All files</string>
<string name="files_structure_directory">Directories</string>
<!-- Browse Layout properties --> <!-- Browse Layout properties -->
<string name="browse_layout_list">List</string> <string name="browse_layout_list">List</string>
<string name="browse_layout_grid">Grid</string> <string name="browse_layout_grid">Grid</string>
@ -314,7 +305,6 @@
<!-- Browse Sort Order properties --> <!-- Browse Sort Order properties -->
<string name="browse_sort_order_name">Alphabetically</string> <string name="browse_sort_order_name">Alphabetically</string>
<string name="browse_sort_order_file_format">File format</string> <string name="browse_sort_order_file_format">File format</string>
<string name="browse_sort_order_file_type">File type</string>
<string name="browse_sort_order_last_modified">Last modified</string> <string name="browse_sort_order_last_modified">Last modified</string>
<string name="browse_sort_order_file_size">File size</string> <string name="browse_sort_order_file_size">File size</string>
@ -392,9 +382,6 @@
<string name="file_size">File size</string> <string name="file_size">File size</string>
<string name="unknown">Unknown</string> <string name="unknown">Unknown</string>
<!-- Browse -->
<string name="internal_storage">Internal Storage</string>
<!-- Reader --> <!-- Reader -->
<string name="no_chapters">No chapters</string> <string name="no_chapters">No chapters</string>
<string name="chapters">Chapters</string> <string name="chapters">Chapters</string>
@ -597,10 +584,7 @@
<string name="cover_image_content_desc">Cover image</string> <string name="cover_image_content_desc">Cover image</string>
<string name="open_reader_settings_content_desc">Reader settings</string> <string name="open_reader_settings_content_desc">Reader settings</string>
<string name="file_icon_content_desc">File</string> <string name="file_icon_content_desc">File</string>
<string name="directory_icon_content_desc">Directory</string>
<string name="favorite_directory_content_desc">Favorite directory</string>
<string name="sort_order_content_desc">Sort order</string> <string name="sort_order_content_desc">Sort order</string>
<string name="path_arrow_icon_content_desc">Path arrow</string>
<string name="checkbox_content_desc">Checkbox</string> <string name="checkbox_content_desc">Checkbox</string>
<string name="cover_image_not_found_content_desc">Cover image not found</string> <string name="cover_image_not_found_content_desc">Cover image not found</string>
<string name="apply_changes_content_desc">Apply changes</string> <string name="apply_changes_content_desc">Apply changes</string>