From 88c4f51ed92683d9b67fd52ad6e46d50d9e0167f Mon Sep 17 00:00:00 2001 From: mdrlzy Date: Fri, 29 Oct 2021 14:46:46 +0500 Subject: [PATCH] File system monitoring --- app/build.gradle | 2 + .../arknavigator/di/modules/RepoModule.kt | 21 ++++++- .../arknavigator/mvp/model/IndexCache.kt | 45 ++++++++++++--- .../arknavigator/mvp/model/IndexingEngine.kt | 27 ++++----- .../arknavigator/mvp/model/RootAndFav.kt | 10 +++- .../taran/arknavigator/mvp/model/TagsCache.kt | 36 +++++++++--- .../model/fsmonitoring/DirectoryObserver.kt | 37 ++++++++++++ .../mvp/model/fsmonitoring/FSMonitoring.kt | 56 +++++++++++++++++++ .../RecursiveDirectoryObserver.kt | 38 +++++++++++++ .../mvp/presenter/FoldersPresenter.kt | 1 + .../mvp/presenter/GalleryPresenter.kt | 11 +++- .../mvp/presenter/ResourcesPresenter.kt | 2 +- .../adapter/ResourcesGridPresenter.kt | 8 +-- .../taran/arknavigator/navigation/Screens.kt | 14 +++-- .../java/space/taran/arknavigator/ui/App.kt | 3 + .../ui/fragments/GalleryFragment.kt | 4 +- .../taran/arknavigator/utils/FSEventLogger.kt | 33 +++++++++++ .../taran/arknavigator/utils/FileUtils.kt | 3 + 18 files changed, 299 insertions(+), 52 deletions(-) create mode 100644 app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/DirectoryObserver.kt create mode 100644 app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/FSMonitoring.kt create mode 100644 app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/RecursiveDirectoryObserver.kt create mode 100644 app/src/main/java/space/taran/arknavigator/utils/FSEventLogger.kt diff --git a/app/build.gradle b/app/build.gradle index 5961a522..dd4c644c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -49,6 +49,8 @@ dependencies { implementation "androidx.recyclerview:recyclerview:1.2.1" implementation "androidx.documentfile:documentfile:1.0.1" + implementation 'com.jakewharton.timber:timber:5.0.1' + implementation "com.github.moxy-community:moxy:2.1.2" implementation "com.github.moxy-community:moxy-androidx:2.1.2" implementation "com.github.moxy-community:moxy-ktx:2.1.2" diff --git a/app/src/main/java/space/taran/arknavigator/di/modules/RepoModule.kt b/app/src/main/java/space/taran/arknavigator/di/modules/RepoModule.kt index b3f1d3e4..87359c58 100644 --- a/app/src/main/java/space/taran/arknavigator/di/modules/RepoModule.kt +++ b/app/src/main/java/space/taran/arknavigator/di/modules/RepoModule.kt @@ -4,9 +4,13 @@ import android.util.Log import space.taran.arknavigator.mvp.model.dao.Database import dagger.Module import dagger.Provides +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob import space.taran.arknavigator.mvp.model.IndexCache import space.taran.arknavigator.mvp.model.IndexingEngine import space.taran.arknavigator.mvp.model.TagsCache +import space.taran.arknavigator.mvp.model.fsmonitoring.FSMonitoring import space.taran.arknavigator.mvp.model.repo.FoldersRepo import space.taran.arknavigator.mvp.model.repo.ResourcesIndexFactory import javax.inject.Singleton @@ -39,14 +43,27 @@ class RepoModule { return TagsCache(indexCache) } + @Singleton + @Provides + fun appCoroutineScope(): CoroutineScope { + return CoroutineScope(SupervisorJob() + Dispatchers.Default) + } + + @Singleton + @Provides + fun fsMonitoring(indexCache: IndexCache, tagsCache: TagsCache, appScope: CoroutineScope): FSMonitoring { + return FSMonitoring(indexCache, tagsCache, appScope) + } + @Singleton @Provides fun indexingEngine( foldersRepo: FoldersRepo, indexCache: IndexCache, tagsCache: TagsCache, - resourcesIndexFactory: ResourcesIndexFactory + resourcesIndexFactory: ResourcesIndexFactory, + fsMonitoring: FSMonitoring ): IndexingEngine { - return IndexingEngine(indexCache, tagsCache, foldersRepo, resourcesIndexFactory) + return IndexingEngine(indexCache, tagsCache, foldersRepo, resourcesIndexFactory, fsMonitoring) } } \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/IndexCache.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/IndexCache.kt index 82e0b0dd..2333401e 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/IndexCache.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/IndexCache.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import space.taran.arknavigator.mvp.model.dao.ResourceId import space.taran.arknavigator.mvp.model.repo.AggregatedResourcesIndex +import space.taran.arknavigator.mvp.model.repo.Difference import space.taran.arknavigator.mvp.model.repo.PlainResourcesIndex import java.nio.file.Path @@ -15,21 +16,35 @@ class IndexCache { suspend fun onIndexChange(root: Path, index: PlainResourcesIndex) { indexByRoot[root] = index - aggregatedIndex = AggregatedResourcesIndex(indexByRoot.values) - val affectedRootAndFavs = flowByRootAndFav.keys.filter { it.root == root } - affectedRootAndFavs.forEach { - flowByRootAndFav[it]!!.emit(indexByRoot[root]!!.listIds(it.fav)) - } + emitChangesToAffectedRootAndFav(root, index) + } + + suspend fun onResourceCreated(root: Path, resourcePath: Path) { + val index = indexByRoot[root]!! + index.reindexRoot(Difference(emptyList(), emptyList(), listOf(resourcePath))) + emitChangesToAffectedRootAndFav(root, index) + } + + suspend fun onResourceDeleted(root: Path, resourcePath: Path): ResourceId { + val index = indexByRoot[root]!! + val id = index.metaByPath[resourcePath]!!.id + index.remove(id) + emitChangesToAffectedRootAndFav(root, indexByRoot[root]!!) + return id + } + + suspend fun onResourceModified(root: Path, resourcePath: Path): PlainResourcesIndex { + val index = indexByRoot[root]!! + index.reindexRoot(Difference(emptyList(), listOf(resourcePath), emptyList())) + emitChangesToAffectedRootAndFav(root, index) + return index } suspend fun onReindexFinish() { allRootsFlow.emit(aggregatedIndex.listAllIds()) } - fun remove(resourceId: ResourceId): Path? { - val path = aggregatedIndex.remove(resourceId) - return path - } + fun getIndexByRoot(root: Path) = indexByRoot[root]!! fun listenResourcesChanges(rootAndFav: RootAndFav): StateFlow?> { return if (rootAndFav.isAllRoots()) { @@ -56,4 +71,16 @@ class IndexCache { fun getPath(resourceId: ResourceId): Path? { return aggregatedIndex.getPath(resourceId) } + + private suspend fun emitChangesToAffectedRootAndFav(root: Path, index: PlainResourcesIndex) { + aggregatedIndex = AggregatedResourcesIndex(indexByRoot.values) + if (allRootsFlow.value != null) + allRootsFlow.emit(aggregatedIndex.listAllIds()) + + val affectedRootAndFavs = flowByRootAndFav.keys.filter { it.root == root } + affectedRootAndFavs.forEach { + if (flowByRootAndFav[it]!!.value != index.listIds(it.fav)) + flowByRootAndFav[it]!!.emit(index.listIds(it.fav)) + } + } } \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/IndexingEngine.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/IndexingEngine.kt index 19bc612f..0d9bfcbc 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/IndexingEngine.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/IndexingEngine.kt @@ -1,38 +1,35 @@ package space.taran.arknavigator.mvp.model -import space.taran.arknavigator.mvp.model.dao.ResourceId +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import space.taran.arknavigator.mvp.model.fsmonitoring.FSMonitoring import space.taran.arknavigator.mvp.model.repo.FoldersRepo import space.taran.arknavigator.mvp.model.repo.ResourcesIndexFactory -import java.nio.file.Files import java.nio.file.Path class IndexingEngine( private val indexCache: IndexCache, private val tagsCache: TagsCache, private val foldersRepo: FoldersRepo, - private val resourcesIndexFactory: ResourcesIndexFactory + private val resourcesIndexFactory: ResourcesIndexFactory, + private val fsMonitoring: FSMonitoring ) { - suspend fun reindex() { + suspend fun reindex() = withContext(Dispatchers.Default) { val roots = foldersRepo.query().succeeded.keys roots.forEach { val index = resourcesIndexFactory.loadFromDatabase(it) tagsCache.onIndexChanged(it, index) indexCache.onIndexChange(it, index) + fsMonitoring.startWatchingRoot(it.toString()) } indexCache.onReindexFinish() tagsCache.onReindexFinish() } - suspend fun index(path: Path) { - val index = resourcesIndexFactory.buildFromFilesystem(path) - indexCache.onIndexChange(path, index) - tagsCache.onIndexChanged(path, index) - } - - suspend fun remove(resourceId: ResourceId): Path? { - val path = indexCache.remove(resourceId) - tagsCache.remove(resourceId) - Files.delete(path) - return path + suspend fun index(root: Path) = withContext(Dispatchers.Default) { + val index = resourcesIndexFactory.buildFromFilesystem(root) + indexCache.onIndexChange(root, index) + tagsCache.onIndexChanged(root, index) + fsMonitoring.startWatchingRoot(root.toString()) } } \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/RootAndFav.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/RootAndFav.kt index bb909e0f..c945bb85 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/RootAndFav.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/RootAndFav.kt @@ -3,11 +3,15 @@ package space.taran.arknavigator.mvp.model import java.nio.file.Path data class RootAndFav ( - var root: Path?, - var fav: Path? + val root: Path?, + val fav: Path? ) { + init { + if (root == null && fav != null) + throw AssertionError("Combination null root and not null fav isn't allowed") + } fun isAllRoots(): Boolean { - return root == null && fav == null + return root == null } } \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/TagsCache.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/TagsCache.kt index 4108435e..f2fc4f82 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/TagsCache.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/TagsCache.kt @@ -2,7 +2,6 @@ package space.taran.arknavigator.mvp.model import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.collect import space.taran.arknavigator.mvp.model.dao.ResourceId import space.taran.arknavigator.mvp.model.repo.AggregatedTagsStorage import space.taran.arknavigator.mvp.model.repo.PlainResourcesIndex @@ -21,11 +20,7 @@ class TagsCache(val indexCache: IndexCache) { storageByRoot[root] = storage val allIds = index.listAllIds() storage.cleanup(allIds) - aggregatedTagsStorage = AggregatedTagsStorage(storageByRoot.values) - val affectedRootAndFavs = flowByRootAndFav.keys.filter { it.root == root } - affectedRootAndFavs.forEach { - flowByRootAndFav[it]!!.emit(storage.getTags(index.listIds(it.fav))) - } + emitChangesToAffectedRootAndFav(root, storage, index) } suspend fun onReindexFinish() { @@ -81,7 +76,32 @@ class TagsCache(val indexCache: IndexCache) { aggregatedTagsStorage.remove(resourceId) } - suspend fun setTags(id: ResourceId, tags: Tags) { - aggregatedTagsStorage.setTags(id, tags) + suspend fun setTags(rootAndFav: RootAndFav, id: ResourceId, tags: Tags) { + if (rootAndFav.isAllRoots()) { + aggregatedTagsStorage.setTags(id, tags) + emitChangesToAllRootsFlow() + } else { + val root = rootAndFav.root!! + val storage = storageByRoot[root]!! + storage.setTags(id, tags) + emitChangesToAffectedRootAndFav(root, storage, indexCache.getIndexByRoot(root)) + } + } + + private suspend fun emitChangesToAllRootsFlow() { + aggregatedTagsStorage = AggregatedTagsStorage(storageByRoot.values) + if (allRootsFlow.value != null) + allRootsFlow.emit(aggregatedTagsStorage.getTags(indexCache.listIds(RootAndFav(null, null)))) + } + + private suspend fun emitChangesToAffectedRootAndFav(root: Path, storage: PlainTagsStorage, index: PlainResourcesIndex) { + emitChangesToAllRootsFlow() + + val affectedRootAndFavs = flowByRootAndFav.keys.filter { it.root == root } + affectedRootAndFavs.forEach { + val tags = storage.getTags(index.listIds(it.fav)) + if (flowByRootAndFav[it]!!.value != tags) + flowByRootAndFav[it]!!.emit(tags) + } } } \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/DirectoryObserver.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/DirectoryObserver.kt new file mode 100644 index 00000000..65e064e5 --- /dev/null +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/DirectoryObserver.kt @@ -0,0 +1,37 @@ +package space.taran.arknavigator.mvp.model.fsmonitoring + +import android.os.Build +import android.os.FileObserver +import androidx.annotation.RequiresApi +import java.io.File + +class DirectoryObserver: FileObserver { + @RequiresApi(Build.VERSION_CODES.Q) + constructor(directory: File): super(directory) + constructor(directory: String): super(directory) + + private lateinit var recursiveObs: RecursiveDirectoryObserver + private lateinit var directory: String + + override fun onEvent(event: Int, path: String?) { + val eventCode = event and ALL_EVENTS + val eventPath = path?.let { "$directory/$path" } + recursiveObs.onEvent(directory, eventCode, eventPath) + } + + companion object { + fun create(recursiveObs: RecursiveDirectoryObserver, directory: String): DirectoryObserver { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + DirectoryObserver(File(directory)).also { + it.recursiveObs = recursiveObs + it.directory = directory + } + } else { + DirectoryObserver(directory).also { + it.recursiveObs = recursiveObs + it.directory = directory + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/FSMonitoring.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/FSMonitoring.kt new file mode 100644 index 00000000..f370bf5c --- /dev/null +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/FSMonitoring.kt @@ -0,0 +1,56 @@ +package space.taran.arknavigator.mvp.model.fsmonitoring + +import android.os.FileObserver +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import space.taran.arknavigator.mvp.model.IndexCache +import space.taran.arknavigator.mvp.model.TagsCache +import space.taran.arknavigator.utils.isTagsStorage +import java.nio.file.Path + +class FSMonitoring( + val indexCache: IndexCache, + val tagsCache: TagsCache, + val appScope: CoroutineScope +) { + private val rootObservers = mutableListOf() + + fun startWatchingRoot(root: String) { + val obs = RecursiveDirectoryObserver(this, root) + rootObservers.add(obs) + obs.startWatching() + } + + fun onEvent(root: Path, directory: Path, event: Int, eventPath: Path?) { + when (event) { + FileObserver.CREATE -> {} + FileObserver.CLOSE_WRITE -> onCloseWrite(root, directory, eventPath!!) + FileObserver.DELETE -> onDelete(root, directory, eventPath!!) + FileObserver.MOVE_SELF -> {} + FileObserver.MOVED_FROM -> onMovedFrom(root, directory, eventPath!!) + FileObserver.MOVED_TO -> onMovedTo(root, directory, eventPath!!) + FileObserver.DELETE_SELF -> {} + } + } + + private fun onCloseWrite(root: Path, directory: Path, eventPath: Path) = appScope.launch(Dispatchers.Default) { + if (!isTagsStorage(eventPath)) { + val index = indexCache.onResourceModified(root, eventPath) + tagsCache.onIndexChanged(root, index) + } + } + + private fun onDelete(root: Path, directory: Path, eventPath: Path) = appScope.launch(Dispatchers.Default) { + val id = indexCache.onResourceDeleted(root, eventPath) + tagsCache.remove(id) + } + + private fun onMovedFrom(root: Path, directory: Path, eventPath: Path) = appScope.launch(Dispatchers.Default) { + indexCache.onResourceDeleted(root, eventPath) + } + + private fun onMovedTo(root: Path, directory: Path, eventPath: Path) = appScope.launch(Dispatchers.Default) { + indexCache.onResourceCreated(root, eventPath) + } +} \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/RecursiveDirectoryObserver.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/RecursiveDirectoryObserver.kt new file mode 100644 index 00000000..524cd14f --- /dev/null +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/fsmonitoring/RecursiveDirectoryObserver.kt @@ -0,0 +1,38 @@ +package space.taran.arknavigator.mvp.model.fsmonitoring + +import space.taran.arknavigator.utils.FSEventLogger +import java.io.File +import java.util.* +import kotlin.io.path.Path + +class RecursiveDirectoryObserver( + private val fsMonitoring: FSMonitoring, + private val root: String +) { + var directoryObservers: MutableList = mutableListOf() + + fun startWatching() { + directoryObservers = mutableListOf() + val stack: Stack = Stack() + stack.push(root) + while (!stack.empty()) { + val parent: String = stack.pop() + directoryObservers.add(DirectoryObserver.create(this, parent)) + val path = File(parent) + val files: Array = path.listFiles() ?: continue + for (i in files.indices) { + if (files[i].isDirectory && !files[i].name.equals(".") + && !files[i].name.equals("..") + ) { + stack.push(files[i].path) + } + } + } + for (i in directoryObservers.indices) directoryObservers[i].startWatching() + } + + fun onEvent(directory: String, event: Int, eventPath: String?) { + FSEventLogger.log(directory, event, eventPath) + fsMonitoring.onEvent(Path(root), Path(directory), event, eventPath?.let { Path(it) }) + } +} \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/mvp/presenter/FoldersPresenter.kt b/app/src/main/java/space/taran/arknavigator/mvp/presenter/FoldersPresenter.kt index d176ecf0..e523053b 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/presenter/FoldersPresenter.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/presenter/FoldersPresenter.kt @@ -9,6 +9,7 @@ import moxy.presenterScope import ru.terrakok.cicerone.Router import space.taran.arknavigator.R import space.taran.arknavigator.mvp.model.IndexingEngine +import space.taran.arknavigator.mvp.model.RootAndFav import space.taran.arknavigator.mvp.model.repo.FoldersRepo import space.taran.arknavigator.mvp.model.repo.ResourcesIndexFactory import space.taran.arknavigator.mvp.presenter.adapter.folderstree.FoldersTreePresenter diff --git a/app/src/main/java/space/taran/arknavigator/mvp/presenter/GalleryPresenter.kt b/app/src/main/java/space/taran/arknavigator/mvp/presenter/GalleryPresenter.kt index aefc2971..bb242234 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/presenter/GalleryPresenter.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/presenter/GalleryPresenter.kt @@ -6,7 +6,9 @@ import kotlinx.coroutines.launch import moxy.MvpPresenter import moxy.presenterScope import ru.terrakok.cicerone.Router +import space.taran.arknavigator.mvp.model.IndexCache import space.taran.arknavigator.mvp.model.IndexingEngine +import space.taran.arknavigator.mvp.model.RootAndFav import space.taran.arknavigator.mvp.model.TagsCache import space.taran.arknavigator.mvp.model.dao.ResourceId import space.taran.arknavigator.mvp.presenter.adapter.PreviewsList @@ -15,9 +17,11 @@ import space.taran.arknavigator.mvp.view.item.PreviewItemView import space.taran.arknavigator.ui.App import space.taran.arknavigator.utils.GALLERY_SCREEN import space.taran.arknavigator.utils.Tags +import java.nio.file.Files import javax.inject.Inject class GalleryPresenter( + private val rootAndFav: RootAndFav, private val resources: MutableList) : MvpPresenter() { @@ -27,7 +31,7 @@ class GalleryPresenter( lateinit var router: Router @Inject - lateinit var indexingEngine: IndexingEngine + lateinit var indexCache: IndexCache @Inject lateinit var tagsCache: TagsCache @@ -46,7 +50,8 @@ class GalleryPresenter( fun deleteResource(resource: ResourceId) = presenterScope.launch(NonCancellable) { Log.d(GALLERY_SCREEN, "deleting resource $resource") - val path = indexingEngine.remove(resource) + val path = indexCache.getPath(resource) + Files.delete(path) Log.d(GALLERY_SCREEN, "path $path removed from index") } @@ -58,7 +63,7 @@ class GalleryPresenter( fun replaceTags(resource: ResourceId, tags: Tags) = presenterScope.launch(NonCancellable) { Log.d(GALLERY_SCREEN, "tags $tags set to $resource") - tagsCache.setTags(resource, tags) + tagsCache.setTags(rootAndFav, resource, tags) } fun onSystemUIVisibilityChange(isVisible: Boolean) { diff --git a/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt b/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt index 4be03ae2..e68e998c 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt @@ -36,7 +36,7 @@ class ResourcesPresenter( var tagsEnabled: Boolean = true - val gridPresenter = ResourcesGridPresenter(viewState, presenterScope).apply { + val gridPresenter = ResourcesGridPresenter(rootAndFav, viewState, presenterScope).apply { App.instance.appComponent.inject(this) } val tagsSelectorPresenter = TagsSelectorPresenter(viewState, rootAndFav, ::onSelectionChange).apply { diff --git a/app/src/main/java/space/taran/arknavigator/mvp/presenter/adapter/ResourcesGridPresenter.kt b/app/src/main/java/space/taran/arknavigator/mvp/presenter/adapter/ResourcesGridPresenter.kt index 8dffc3bf..e09775d0 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/presenter/adapter/ResourcesGridPresenter.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/presenter/adapter/ResourcesGridPresenter.kt @@ -3,10 +3,7 @@ package space.taran.arknavigator.mvp.presenter.adapter import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import ru.terrakok.cicerone.Router -import space.taran.arknavigator.mvp.model.IndexCache -import space.taran.arknavigator.mvp.model.IndexingEngine -import space.taran.arknavigator.mvp.model.TagsCache -import space.taran.arknavigator.mvp.model.UserPreferences +import space.taran.arknavigator.mvp.model.* import space.taran.arknavigator.mvp.model.dao.ResourceId import space.taran.arknavigator.mvp.view.ResourcesView import space.taran.arknavigator.mvp.view.item.FileItemView @@ -19,6 +16,7 @@ import java.nio.file.Files import javax.inject.Inject class ResourcesGridPresenter( + val rootAndFav: RootAndFav, val viewState: ResourcesView, val scope: CoroutineScope ) { @@ -64,7 +62,7 @@ class ResourcesGridPresenter( } fun onItemClick(pos: Int) { - router.navigateTo(Screens.GalleryScreen(selection, pos)) + router.navigateTo(Screens.GalleryScreen(rootAndFav, selection, pos)) } suspend fun init() { diff --git a/app/src/main/java/space/taran/arknavigator/navigation/Screens.kt b/app/src/main/java/space/taran/arknavigator/navigation/Screens.kt index 00352f38..99e3e3a0 100644 --- a/app/src/main/java/space/taran/arknavigator/navigation/Screens.kt +++ b/app/src/main/java/space/taran/arknavigator/navigation/Screens.kt @@ -2,22 +2,26 @@ package space.taran.arknavigator.navigation import space.taran.arknavigator.ui.fragments.* import ru.terrakok.cicerone.android.support.SupportAppScreen +import space.taran.arknavigator.mvp.model.RootAndFav import space.taran.arknavigator.mvp.model.dao.ResourceId import space.taran.arknavigator.mvp.model.repo.ResourcesIndex import space.taran.arknavigator.mvp.model.repo.TagsStorage import java.nio.file.Path class Screens { - class FoldersScreen: SupportAppScreen() { + class FoldersScreen : SupportAppScreen() { override fun getFragment() = FoldersFragment() } - class ResourcesScreen(val root: Path?, val path: Path?): SupportAppScreen() { + class ResourcesScreen(val root: Path?, val path: Path?) : SupportAppScreen() { override fun getFragment() = ResourcesFragment(root, path) } - class GalleryScreen(val resources: List, - val position: Int): SupportAppScreen() { - override fun getFragment() = GalleryFragment(resources.toMutableList(), position) + class GalleryScreen( + val rootAndFav: RootAndFav, + val resources: List, + val position: Int + ) : SupportAppScreen() { + override fun getFragment() = GalleryFragment(rootAndFav, resources.toMutableList(), position) } } \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/ui/App.kt b/app/src/main/java/space/taran/arknavigator/ui/App.kt index 2d74c925..eca6f3f9 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/App.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/App.kt @@ -4,6 +4,7 @@ import android.app.Application import space.taran.arknavigator.di.AppComponent import space.taran.arknavigator.di.DaggerAppComponent import space.taran.arknavigator.di.modules.AppModule +import timber.log.Timber class App: Application() { @@ -19,6 +20,8 @@ class App: Application() { instance = this + Timber.plant(Timber.DebugTree()) + appComponent = DaggerAppComponent.builder() .appModule(AppModule(this)) .build() diff --git a/app/src/main/java/space/taran/arknavigator/ui/fragments/GalleryFragment.kt b/app/src/main/java/space/taran/arknavigator/ui/fragments/GalleryFragment.kt index cc865a5c..344c27fd 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/fragments/GalleryFragment.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/fragments/GalleryFragment.kt @@ -20,6 +20,7 @@ import space.taran.arknavigator.databinding.DialogTagsBinding import space.taran.arknavigator.databinding.FragmentGalleryBinding import space.taran.arknavigator.mvp.model.IndexCache import space.taran.arknavigator.mvp.model.IndexingEngine +import space.taran.arknavigator.mvp.model.RootAndFav import space.taran.arknavigator.mvp.model.dao.ResourceId import space.taran.arknavigator.mvp.presenter.GalleryPresenter import space.taran.arknavigator.mvp.presenter.adapter.PreviewsList @@ -36,6 +37,7 @@ import java.io.File import javax.inject.Inject class GalleryFragment( + private val rootAndFav: RootAndFav, private val resources: MutableList, private val startAt: Int ) : MvpAppCompatFragment(), GalleryView, BackButtonListener, NotifiableView { @@ -48,7 +50,7 @@ class GalleryFragment( private lateinit var binding: FragmentGalleryBinding private val presenter by moxyPresenter { - GalleryPresenter(resources).apply { + GalleryPresenter(rootAndFav, resources).apply { Log.d(GALLERY_SCREEN, "creating GalleryPresenter") App.instance.appComponent.inject(this) } diff --git a/app/src/main/java/space/taran/arknavigator/utils/FSEventLogger.kt b/app/src/main/java/space/taran/arknavigator/utils/FSEventLogger.kt new file mode 100644 index 00000000..e99c2bc7 --- /dev/null +++ b/app/src/main/java/space/taran/arknavigator/utils/FSEventLogger.kt @@ -0,0 +1,33 @@ +package space.taran.arknavigator.utils + +import android.os.FileObserver +import timber.log.Timber + +object FSEventLogger { + private const val LOG_UNKNOWN_EVENTS = false + + fun log(directory: String, event: Int, eventPath: String?) { + val eventName = provideEventName(event) + eventName?.let { + Timber.d("$eventName \n Directory: $directory \n Path: $eventPath") + } + } + + private fun provideEventName(event: Int): String? { + return when(event) { + FileObserver.ACCESS -> "ACCESS" + FileObserver.ATTRIB -> "ATTRIB" + FileObserver.CLOSE_NOWRITE -> "CLOSE_NOWRITE" + FileObserver.CLOSE_WRITE -> "CLOSE_WRITE" + FileObserver.CREATE -> "CREATE" + FileObserver.DELETE -> "DELETE" + FileObserver.DELETE_SELF -> "DELETE_SELF" + FileObserver.MODIFY -> "MODIFY" + FileObserver.MOVED_FROM -> "MOVED_FROM" + FileObserver.MOVED_TO -> "MOVED_TO" + FileObserver.MOVE_SELF -> "MOVE_SELF" + FileObserver.OPEN -> "OPEN" + else -> if (LOG_UNKNOWN_EVENTS) "Unknown event code $event" else null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/space/taran/arknavigator/utils/FileUtils.kt b/app/src/main/java/space/taran/arknavigator/utils/FileUtils.kt index 4b67dc9f..988dbad8 100644 --- a/app/src/main/java/space/taran/arknavigator/utils/FileUtils.kt +++ b/app/src/main/java/space/taran/arknavigator/utils/FileUtils.kt @@ -1,5 +1,6 @@ package space.taran.arknavigator.utils +import space.taran.arknavigator.mvp.model.repo.PlainTagsStorage import space.taran.arknavigator.ui.App import java.lang.IllegalArgumentException import java.nio.file.Files @@ -57,6 +58,8 @@ fun getFileActionType(filePath: Path): FileActionType{ } } +fun isTagsStorage(path: Path): Boolean = path.fileName.toString() == PlainTagsStorage.STORAGE_FILENAME + fun isHidden(path: Path): Boolean = path.fileName.toString().startsWith('.')