From 56238425ae3198d369d80e826343a32c7452b498 Mon Sep 17 00:00:00 2001 From: ShubertMunthali Date: Fri, 24 Mar 2023 14:05:13 +0200 Subject: [PATCH 1/6] Corrupted tags storage notification --- .../model/repo/tags/AggregatedTagsStorage.kt | 2 + .../mvp/model/repo/tags/PlainTagsStorage.kt | 23 +++++-- .../mvp/model/repo/tags/TagsStorage.kt | 2 + .../mvp/presenter/GalleryPresenter.kt | 6 ++ .../mvp/presenter/ResourcesPresenter.kt | 5 ++ .../arknavigator/mvp/view/GalleryView.kt | 3 + .../arknavigator/mvp/view/ResourcesView.kt | 2 + .../ui/fragments/GalleryFragment.kt | 8 +++ .../ui/fragments/ResourcesFragment.kt | 17 +++++ ...ageCorruptionNotificationDialogFragment.kt | 64 +++++++++++++++++ .../main/res/layout/dialog_notification.xml | 68 +++++++++++++++++++ app/src/main/res/values/strings.xml | 5 ++ 12 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/StorageCorruptionNotificationDialogFragment.kt create mode 100644 app/src/main/res/layout/dialog_notification.xml diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/AggregatedTagsStorage.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/AggregatedTagsStorage.kt index 3472abe5..350c14cb 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/AggregatedTagsStorage.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/AggregatedTagsStorage.kt @@ -55,4 +55,6 @@ class AggregatedTagsStorage( shards.forEach { it.remove(id) } + + override fun isCorrupted() = shards.any { it.isCorrupted() } } diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt index b02f9900..f01f9e01 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt @@ -42,6 +42,8 @@ class PlainTagsStorage( private lateinit var tagsById: MutableMap + private var isCorrupted = false + suspend fun init() = withContext(Dispatchers.IO) { val result = resources.map { it to NO_TAGS } .toMap() @@ -144,6 +146,8 @@ class PlainTagsStorage( persist() } + override fun isCorrupted() = isCorrupted + override fun setTags(id: ResourceId, tags: Tags) { if (!tagsById.containsKey(id)) { error("Storage isn't aware about this resource id") @@ -230,21 +234,24 @@ class PlainTagsStorage( val lines = Files.readAllLines(storageFile, StandardCharsets.UTF_8) verifyVersion(lines.removeAt(0)) - val result = lines + val result = mutableMapOf() + lines .map { + if (!it.contains(KEY_VALUE_SEPARATOR)) { + isCorrupted = true + return@map + } + val parts = it.split(KEY_VALUE_SEPARATOR) val id = ResourceId.fromString(parts[0]) val tags = tagsFromString(parts[1]) if (tags.isEmpty()) { - throw AssertionError( - "Tags storage must not contain empty sets of tags" - ) + isCorrupted = tags.isEmpty() + return@map } - - id to tags + result[id] = tags } - .toMap() if (result.isEmpty()) { throw AssertionError("Tags storage must not be empty") @@ -281,6 +288,8 @@ class PlainTagsStorage( private const val STORAGE_VERSION = 2 private const val STORAGE_VERSION_PREFIX = "version " + const val TYPE = "Tags" + const val KEY_VALUE_SEPARATOR = ':' private fun verifyVersion(header: String) { diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/TagsStorage.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/TagsStorage.kt index 96bed09f..6ae32197 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/TagsStorage.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/TagsStorage.kt @@ -26,4 +26,6 @@ interface TagsStorage { suspend fun cleanup(existing: Collection) suspend fun remove(id: ResourceId) + + fun isCorrupted(): Boolean } 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 a11aaf58..492dcab6 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 @@ -29,6 +29,7 @@ import space.taran.arknavigator.mvp.model.repo.scores.ScoreStorage import space.taran.arknavigator.mvp.model.repo.scores.ScoreStorageRepo import space.taran.arknavigator.mvp.model.repo.stats.StatsStorage import space.taran.arknavigator.mvp.model.repo.stats.StatsStorageRepo +import space.taran.arknavigator.mvp.model.repo.tags.PlainTagsStorage import space.taran.arknavigator.mvp.model.repo.tags.TagsStorage import space.taran.arknavigator.mvp.model.repo.tags.TagsStorageRepo import space.taran.arknavigator.mvp.presenter.adapter.ResourceMetaDiffUtilCallback @@ -133,6 +134,11 @@ class GalleryPresenter( metadataStorage = metadataStorageRepo.provide(rootAndFav) statsStorage = statsStorageRepo.provide(rootAndFav) scoreStorage = scoreStorageRepo.provide(rootAndFav) + + if (storage.isCorrupted()) viewState.showCorruptNotificationDialog( + PlainTagsStorage.TYPE + ) + resources = resourcesIds.map { index.getMeta(it) }.toMutableList() sortByScores = preferences.get(PreferenceKey.SortByScores) 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 53ce09ad..aeffa0c8 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 @@ -26,6 +26,7 @@ import space.taran.arknavigator.mvp.model.repo.scores.ScoreStorage import space.taran.arknavigator.mvp.model.repo.scores.ScoreStorageRepo import space.taran.arknavigator.mvp.model.repo.stats.StatsStorage import space.taran.arknavigator.mvp.model.repo.stats.StatsStorageRepo +import space.taran.arknavigator.mvp.model.repo.tags.PlainTagsStorage import space.taran.arknavigator.mvp.model.repo.tags.TagsStorage import space.taran.arknavigator.mvp.model.repo.tags.TagsStorageRepo import space.taran.arknavigator.mvp.presenter.adapter.ResourcesGridPresenter @@ -138,6 +139,10 @@ class ResourcesPresenter( statsStorage = statsStorageRepo.provide(rootAndFav) scoreStorage = scoreStorageRepo.provide(rootAndFav) + if (storage.isCorrupted()) viewState.showCorruptNotificationDialog( + PlainTagsStorage.TYPE + ) + gridPresenter.init(index, storage, router, previewStorage, scoreStorage) val resources = index.listResources(rootAndFav.fav) diff --git a/app/src/main/java/space/taran/arknavigator/mvp/view/GalleryView.kt b/app/src/main/java/space/taran/arknavigator/mvp/view/GalleryView.kt index fe9386aa..54560d87 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/view/GalleryView.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/view/GalleryView.kt @@ -71,4 +71,7 @@ interface GalleryView : CommonMvpView { @StateStrategyType(SkipStrategy::class) fun notifySelectedChanged(selected: List) + + @StateStrategyType(SkipStrategy::class) + fun showCorruptNotificationDialog(storageType: String) } diff --git a/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt b/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt index a76d1010..600ce3c9 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt @@ -32,4 +32,6 @@ interface ResourcesView : CommonMvpView { fun clearStackedToasts() @StateStrategyType(SkipStrategy::class) fun shareResources(resources: List) + @StateStrategyType(SkipStrategy::class) + fun showCorruptNotificationDialog(storageType: String) } 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 d1f56759..30cc991e 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 @@ -49,6 +49,7 @@ import space.taran.arknavigator.utils.Tag import space.taran.arknavigator.utils.Tags import space.taran.arknavigator.utils.Score import space.taran.arklib.utils.extension +import space.taran.arknavigator.ui.fragments.dialog.StorageCorruptionNotificationDialogFragment import space.taran.arknavigator.utils.LogTags.GALLERY_SCREEN import space.taran.arknavigator.utils.extensions.makeGone import space.taran.arknavigator.utils.extensions.makeVisible @@ -258,6 +259,13 @@ class GalleryFragment : MvpAppCompatFragment(), GalleryView { } } + override fun showCorruptNotificationDialog(storageType: String) { + StorageCorruptionNotificationDialogFragment.newInstance(storageType).show( + childFragmentManager, + StorageCorruptionNotificationDialogFragment.TAG + ) + } + override fun notifyResourcesChanged() { setFragmentResult(REQUEST_RESOURCES_CHANGED_KEY, bundleOf()) } diff --git a/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt b/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt index 827b2a8e..070b1304 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt @@ -36,6 +36,7 @@ import space.taran.arknavigator.ui.activity.MainActivity import space.taran.arknavigator.ui.adapter.ResourcesRVAdapter import space.taran.arknavigator.ui.adapter.TagsSelectorAdapter import space.taran.arknavigator.ui.fragments.dialog.ConfirmationDialogFragment +import space.taran.arknavigator.ui.fragments.dialog.StorageCorruptionNotificationDialogFragment import space.taran.arknavigator.ui.fragments.dialog.SortDialogFragment import space.taran.arknavigator.ui.fragments.dialog.TagsSortDialogFragment import space.taran.arknavigator.ui.fragments.utils.toast @@ -287,6 +288,14 @@ class ResourcesFragment : MvpAppCompatFragment(), ResourcesView { ) } + override fun showCorruptNotificationDialog(storageType: String) { + StorageCorruptionNotificationDialogFragment.newInstance(storageType) + .show( + childFragmentManager, + StorageCorruptionNotificationDialogFragment.TAG + ) + } + private fun initMenuListeners() = with(binding) { actionBar.ivDisableSelectionMode.setOnClickListener { presenter.gridPresenter.onSelectingChanged(false) @@ -416,6 +425,13 @@ class ResourcesFragment : MvpAppCompatFragment(), ResourcesView { ) } } + + childFragmentManager.setFragmentResultListener( + StorageCorruptionNotificationDialogFragment.STORAGE_CORRUPTION_DETECTED, + this + ) { _, _ -> + presenter.onBackClick() + } } private fun dragHandlerTouchListener(view: View, event: MotionEvent): Boolean { @@ -519,6 +535,7 @@ class ResourcesFragment : MvpAppCompatFragment(), ResourcesView { const val DELETE_CONFIRMATION_REQUEST_KEY = "deleteConfirm" private const val MOVE_TO_PATH_KEY = "moveToPath" const val RESET_SCORES_FOR_SELECTED = "resetSelectedScores" + const val STORAGE_CORRUPTION_DETECTED = "storage corrupted" private const val DRAG_TRAVEL_TIME_THRESHOLD = 30 // milliseconds private const val DRAG_TRAVEL_DELTA_THRESHOLD = 0.1 // ratio diff --git a/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/StorageCorruptionNotificationDialogFragment.kt b/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/StorageCorruptionNotificationDialogFragment.kt new file mode 100644 index 00000000..96678131 --- /dev/null +++ b/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/StorageCorruptionNotificationDialogFragment.kt @@ -0,0 +1,64 @@ +package space.taran.arknavigator.ui.fragments.dialog + +import android.graphics.Color.TRANSPARENT +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.os.bundleOf +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.setFragmentResult +import space.taran.arknavigator.R +import space.taran.arknavigator.databinding.DialogNotificationBinding + +class StorageCorruptionNotificationDialogFragment : DialogFragment() { + + private lateinit var binding: DialogNotificationBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + super.onCreateView(inflater, container, savedInstanceState) + binding = DialogNotificationBinding + .inflate(inflater, container, false) + + dialog?.window?.setBackgroundDrawable(ColorDrawable(TRANSPARENT)) + + val args = requireArguments() + val storageType = args.getString(STORAGE_TYPE_KEY) + + binding.apply { + titleTV.text = getString(R.string.corrupted_storage) + infoTV.text = getString( + R.string.storage_corrupt_info, + storageType + ) + closeBtn.setOnClickListener { + setFragmentResult( + STORAGE_CORRUPTION_DETECTED, + bundleOf() + ) + dismiss() + } + } + + return binding.root + } + + companion object { + const val TAG = "corrupt notification dialog" + const val STORAGE_TYPE_KEY = "storage type key" + const val STORAGE_CORRUPTION_DETECTED = "storage corruption detected" + + fun newInstance( + storageType: String, + ) = StorageCorruptionNotificationDialogFragment().also { + it.arguments = bundleOf().apply { + putString(STORAGE_TYPE_KEY, storageType) + } + } + } +} diff --git a/app/src/main/res/layout/dialog_notification.xml b/app/src/main/res/layout/dialog_notification.xml new file mode 100644 index 00000000..12aa9327 --- /dev/null +++ b/app/src/main/res/layout/dialog_notification.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cd5b0736..67bf7523 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -124,4 +124,9 @@ Utils Navigator will forget the folder and all its children Delete files + Backup + Ignore + Close + Corrupted Storage + %1$s storage is corrupted. \nGo back to folders From ef0c07f7f983ceb448b6cff92e1af45c10ab7e9f Mon Sep 17 00:00:00 2001 From: ShubertMunthali Date: Fri, 24 Mar 2023 14:23:03 +0200 Subject: [PATCH 2/6] Corrupted tags storage notification --- .../arknavigator/mvp/presenter/ResourcesPresenter.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 aeffa0c8..9705fcd3 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 @@ -135,14 +135,16 @@ class ResourcesPresenter( }.launchIn(presenterScope) index.reindex() storage = tagsStorageRepo.provide(rootAndFav) + if (storage.isCorrupted()) { + viewState.showCorruptNotificationDialog( + PlainTagsStorage.TYPE + ) + return@launch + } previewStorage = previewStorageRepo.provide(rootAndFav) statsStorage = statsStorageRepo.provide(rootAndFav) scoreStorage = scoreStorageRepo.provide(rootAndFav) - if (storage.isCorrupted()) viewState.showCorruptNotificationDialog( - PlainTagsStorage.TYPE - ) - gridPresenter.init(index, storage, router, previewStorage, scoreStorage) val resources = index.listResources(rootAndFav.fav) From 546c941a8053ad74dc28b4953d9510be89bf8ab2 Mon Sep 17 00:00:00 2001 From: ShubertMunthali Date: Sun, 26 Mar 2023 10:18:14 +0200 Subject: [PATCH 3/6] Corrupted tags storage notification --- .../mvp/model/repo/tags/PlainTagsStorage.kt | 27 +++++++++---------- .../arknavigator/stub/TagsStorageStub.kt | 2 ++ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt index f01f9e01..a1e6f598 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt @@ -130,11 +130,13 @@ class PlainTagsStorage( override suspend fun cleanup(existing: Collection) = withContext(Dispatchers.IO) { - val disappeared = tagsById.keys.minus(existing) + if (!isCorrupted) { + val disappeared = tagsById.keys.minus(existing) - Log.d(TAGS_STORAGE, "forgetting ${disappeared.size} resources") - disappeared.forEach { tagsById.remove(it) } - persist() + Log.d(TAGS_STORAGE, "forgetting ${disappeared.size} resources") + disappeared.forEach { tagsById.remove(it) } + persist() + } } override suspend fun remove(id: ResourceId) = withContext(Dispatchers.IO) { @@ -235,23 +237,18 @@ class PlainTagsStorage( verifyVersion(lines.removeAt(0)) val result = mutableMapOf() - lines - .map { - if (!it.contains(KEY_VALUE_SEPARATOR)) { - isCorrupted = true - return@map - } + try { + lines.map { val parts = it.split(KEY_VALUE_SEPARATOR) val id = ResourceId.fromString(parts[0]) val tags = tagsFromString(parts[1]) - - if (tags.isEmpty()) { - isCorrupted = tags.isEmpty() - return@map - } + isCorrupted = tags.isEmpty() result[id] = tags } + } catch (e: Exception) { + isCorrupted = true + } if (result.isEmpty()) { throw AssertionError("Tags storage must not be empty") diff --git a/app/src/test/java/space/taran/arknavigator/stub/TagsStorageStub.kt b/app/src/test/java/space/taran/arknavigator/stub/TagsStorageStub.kt index 51863fd4..de0dda88 100644 --- a/app/src/test/java/space/taran/arknavigator/stub/TagsStorageStub.kt +++ b/app/src/test/java/space/taran/arknavigator/stub/TagsStorageStub.kt @@ -35,4 +35,6 @@ class TagsStorageStub : TagsStorage { override suspend fun remove(id: ResourceId) { tagsById.remove(id) } + + override fun isCorrupted() = false } From da67ca0090fe310a5be62856b83f31f844297a51 Mon Sep 17 00:00:00 2001 From: ShubertMunthali Date: Thu, 6 Apr 2023 19:45:35 +0200 Subject: [PATCH 4/6] Stop reading on empty tags --- .../arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt | 5 ++++- .../taran/arknavigator/ui/fragments/GalleryFragment.kt | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt index a1e6f598..49009d8f 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt @@ -243,7 +243,10 @@ class PlainTagsStorage( val parts = it.split(KEY_VALUE_SEPARATOR) val id = ResourceId.fromString(parts[0]) val tags = tagsFromString(parts[1]) - isCorrupted = tags.isEmpty() + if (tags.isEmpty()) { + isCorrupted = true + return@map + } result[id] = tags } } catch (e: Exception) { 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 30cc991e..b647e0f9 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 @@ -55,6 +55,7 @@ import space.taran.arknavigator.utils.extensions.makeGone import space.taran.arknavigator.utils.extensions.makeVisible import timber.log.Timber import java.nio.file.Path +import kotlin.system.measureTimeMillis class GalleryFragment : MvpAppCompatFragment(), GalleryView { @@ -121,7 +122,10 @@ class GalleryFragment : MvpAppCompatFragment(), GalleryView { fabStartSelect.isVisible = !selectingEnabled removeResourceFab.setOnLongClickListener { - presenter.onRemoveFabClick() + val time = measureTimeMillis { + presenter.onRemoveFabClick() + } + Timber.tag(GALLERY_SCREEN).d("${time / 1000L}s") true } From 68733ce1bff1ca9edbb8211f5e27c292dfcc68c3 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Mon, 10 Apr 2023 21:48:28 +0300 Subject: [PATCH 5/6] Fix for case when line with empty tags is in the middle --- .../mvp/model/repo/tags/PlainTagsStorage.kt | 32 +++++++++---------- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt index 49009d8f..68ac7e7a 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt @@ -231,34 +231,34 @@ class PlainTagsStorage( writeStorage() } - private suspend fun readStorage(): Map = + private suspend fun readStorage(): Result> = withContext(Dispatchers.IO) { val lines = Files.readAllLines(storageFile, StandardCharsets.UTF_8) verifyVersion(lines.removeAt(0)) - val result = mutableMapOf() - try { - lines.map { + val tagsById = lines.map { val parts = it.split(KEY_VALUE_SEPARATOR) val id = ResourceId.fromString(parts[0]) val tags = tagsFromString(parts[1]) - if (tags.isEmpty()) { - isCorrupted = true - return@map - } - result[id] = tags + id to tags + } + + if (tagsById.any { (id, tags) -> tags.isEmpty() }) { + isCorrupted = true + return Result.failure(StreamCorruptedException()) + } + if (tagsById.isEmpty()) { + isCorrupted = true + return Result.failure(IllegalArgumentException()) } + + Log.d(TAGS_STORAGE, "${tagsById.size} entries has been read") + return@withContext tagsById.toMap() } catch (e: Exception) { isCorrupted = true + return Result.failure(e) } - - if (result.isEmpty()) { - throw AssertionError("Tags storage must not be empty") - } - - Log.d(TAGS_STORAGE, "${result.size} entries has been read") - return@withContext result } private suspend fun writeStorage() = diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 67bf7523..511db780 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -128,5 +128,5 @@ Ignore Close Corrupted Storage - %1$s storage is corrupted. \nGo back to folders + %1$s storage is corrupted. \nOpening the folder isn't safe From c00ae292c04fe3a2a114c2884d4d04491e07bdcd Mon Sep 17 00:00:00 2001 From: ShubertMunthali Date: Tue, 11 Apr 2023 12:55:51 +0200 Subject: [PATCH 6/6] Fix corrupted notification --- .../mvp/model/repo/tags/PlainTagsStorage.kt | 68 +++++++++++-------- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt index 68ac7e7a..c0a5c216 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/model/repo/tags/PlainTagsStorage.kt @@ -18,6 +18,7 @@ import space.taran.arknavigator.utils.Converters.Companion.stringFromTags import space.taran.arknavigator.utils.Converters.Companion.tagsFromString import space.taran.arknavigator.utils.LogTags.TAGS_STORAGE import space.taran.arknavigator.utils.Tags +import java.io.StreamCorruptedException import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path @@ -57,7 +58,9 @@ class PlainTagsStorage( ", last modified at $lastModified" ) - result.putAll(readStorage()) + readStorage().onSuccess { + result.putAll(it) + } } else { Log.d(TAGS_STORAGE, "file $storageFile doesn't exist") } @@ -90,7 +93,9 @@ class PlainTagsStorage( suspend fun readStorageIfChanged() { if (storageFile.notExists()) return if (lastModified != storageFile.getLastModifiedTime()) { - tagsById.putAll(readStorage()) + readStorage().onSuccess { + tagsById.putAll(it) + } } } @@ -196,39 +201,43 @@ class PlainTagsStorage( // without this, we need to stop all competing devices to remove a tag or a resource // so far, just ensuring that we are not losing additions - val outside = readStorage() + readStorage().onSuccess { outside -> + + for (newId in outside.keys - tagsById.keys) { + Log.d( + TAGS_STORAGE, + "resource $newId got first tags from outside" + ) + tagsById[newId] = outside[newId]!! + } - for (newId in outside.keys - tagsById.keys) { - Log.d( - TAGS_STORAGE, - "resource $newId got first tags from outside" - ) - tagsById[newId] = outside[newId]!! + for (sharedId in outside.keys.intersect(tagsById.keys)) { + val theirs = outside[sharedId] + val ours = tagsById[sharedId] + if (theirs != ours) { + Log.d( + TAGS_STORAGE, + "resource $sharedId got new tags " + + "from outside: ${theirs!! - ours}" + ) + tagsById[sharedId] = theirs.union(ours!!) + } + } } - for (sharedId in outside.keys.intersect(tagsById.keys)) { - val theirs = outside[sharedId] - val ours = tagsById[sharedId] - if (theirs != ours) { + if (tagsById.isEmpty() || tagsById.all { it.value.isEmpty() }) { + if (exists) { Log.d( TAGS_STORAGE, - "resource $sharedId got new tags " + - "from outside: ${theirs!! - ours}" + "no tagged resources, deleting storage file" ) - tagsById[sharedId] = theirs.union(ours!!) + Files.delete(storageFile) } + return@withContext } - } - if (tagsById.isEmpty() || tagsById.all { it.value.isEmpty() }) { - if (exists) { - Log.d(TAGS_STORAGE, "no tagged resources, deleting storage file") - Files.delete(storageFile) - } - return@withContext + writeStorage() } - - writeStorage() } private suspend fun readStorage(): Result> = @@ -246,18 +255,19 @@ class PlainTagsStorage( if (tagsById.any { (id, tags) -> tags.isEmpty() }) { isCorrupted = true - return Result.failure(StreamCorruptedException()) + return@withContext Result.failure(StreamCorruptedException()) } + if (tagsById.isEmpty()) { isCorrupted = true - return Result.failure(IllegalArgumentException()) + return@withContext Result.failure(IllegalArgumentException()) } Log.d(TAGS_STORAGE, "${tagsById.size} entries has been read") - return@withContext tagsById.toMap() + return@withContext Result.success(tagsById.toMap()) } catch (e: Exception) { isCorrupted = true - return Result.failure(e) + return@withContext Result.failure(e) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 511db780..2b19f495 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -128,5 +128,5 @@ Ignore Close Corrupted Storage - %1$s storage is corrupted. \nOpening the folder isn't safe + %1$s storage is corrupted. \nOpening the folder isn\'t safe