From 858664bfd741d4e1433573dd1e5672bea197ef2d Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 21 Nov 2020 15:09:56 -0500 Subject: [PATCH] Some more code cleanup --- .../{models => }/AbstractBackupManager.kt | 2 +- .../{models => }/AbstractBackupRestore.kt | 3 +- .../AbstractBackupRestoreValidator.kt | 2 +- .../data/backup/BackupRestoreService.kt | 1 - .../data/backup/full/FullBackupManager.kt | 58 ++++--- .../data/backup/full/FullBackupRestore.kt | 2 +- .../backup/full/FullBackupRestoreValidator.kt | 2 +- .../data/backup/legacy/LegacyBackupManager.kt | 53 +++---- .../data/backup/legacy/LegacyBackupRestore.kt | 2 +- .../legacy/LegacyBackupRestoreValidator.kt | 2 +- .../ui/setting/SettingsBackupController.kt | 141 ++++++++---------- 11 files changed, 121 insertions(+), 147 deletions(-) rename app/src/main/java/eu/kanade/tachiyomi/data/backup/{models => }/AbstractBackupManager.kt (97%) rename app/src/main/java/eu/kanade/tachiyomi/data/backup/{models => }/AbstractBackupRestore.kt (94%) rename app/src/main/java/eu/kanade/tachiyomi/data/backup/{models => }/AbstractBackupRestoreValidator.kt (91%) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt similarity index 97% rename from app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupManager.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt index b1de48b66..0827169d2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt @@ -1,4 +1,4 @@ -package eu.kanade.tachiyomi.data.backup.models +package eu.kanade.tachiyomi.data.backup import android.content.Context import android.net.Uri diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupRestore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestore.kt similarity index 94% rename from app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupRestore.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestore.kt index 6609178af..0c3ff6d74 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupRestore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestore.kt @@ -1,8 +1,7 @@ -package eu.kanade.tachiyomi.data.backup.models +package eu.kanade.tachiyomi.data.backup import android.content.Context import android.net.Uri -import eu.kanade.tachiyomi.data.backup.BackupNotifier import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.track.TrackManager import kotlinx.coroutines.Job diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupRestoreValidator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestoreValidator.kt similarity index 91% rename from app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupRestoreValidator.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestoreValidator.kt index 5e6b42298..2dc959691 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/AbstractBackupRestoreValidator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestoreValidator.kt @@ -1,4 +1,4 @@ -package eu.kanade.tachiyomi.data.backup.models +package eu.kanade.tachiyomi.data.backup import android.content.Context import android.net.Uri diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt index fa94f1fd3..249f5d7c8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt @@ -10,7 +10,6 @@ import androidx.core.content.ContextCompat import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.full.FullBackupRestore import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupRestore -import eu.kanade.tachiyomi.data.backup.models.AbstractBackupRestore import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isServiceRunning diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt index d4e6e12a6..6b1c0501c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.backup.full import android.content.Context import android.net.Uri import com.hippo.unifile.UniFile +import eu.kanade.tachiyomi.data.backup.AbstractBackupManager import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY_MASK import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CHAPTER @@ -20,7 +21,6 @@ import eu.kanade.tachiyomi.data.backup.full.models.BackupManga import eu.kanade.tachiyomi.data.backup.full.models.BackupSerializer import eu.kanade.tachiyomi.data.backup.full.models.BackupSource import eu.kanade.tachiyomi.data.backup.full.models.BackupTracking -import eu.kanade.tachiyomi.data.backup.models.AbstractBackupManager import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.Manga @@ -53,8 +53,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) { var backup: Backup? = null databaseHelper.inTransaction { - // Get manga from database - val databaseManga = getDatabaseManga() + val databaseManga = getFavoriteManga() backup = Backup( backupManga(databaseManga, flags), @@ -64,45 +63,38 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) { } try { - // When BackupCreatorJob - if (isJob) { - // Get dir of file and create - var dir = UniFile.fromUri(context, uri) - dir = dir.createDirectory("automatic") + val file: UniFile = ( + if (isJob) { + // Get dir of file and create + var dir = UniFile.fromUri(context, uri) + dir = dir.createDirectory("automatic") - // Delete older backups - val numberOfBackups = numberOfBackups() - val backupRegex = Regex("""tachiyomi_\d+-\d+-\d+_\d+-\d+.proto.gz""") - dir.listFiles { _, filename -> backupRegex.matches(filename) } - .orEmpty() - .sortedByDescending { it.name } - .drop(numberOfBackups - 1) - .forEach { it.delete() } + // Delete older backups + val numberOfBackups = numberOfBackups() + val backupRegex = Regex("""tachiyomi_\d+-\d+-\d+_\d+-\d+.proto.gz""") + dir.listFiles { _, filename -> backupRegex.matches(filename) } + .orEmpty() + .sortedByDescending { it.name } + .drop(numberOfBackups - 1) + .forEach { it.delete() } - // Create new file to place backup - val newFile = dir.createFile(BackupFull.getDefaultFilename()) - ?: throw Exception("Couldn't create backup file") + // Create new file to place backup + dir.createFile(BackupFull.getDefaultFilename()) + } else { + UniFile.fromUri(context, uri) + } + ) + ?: throw Exception("Couldn't create backup file") - val byteArray = parser.encodeToByteArray(BackupSerializer, backup!!) - newFile.openOutputStream().sink().gzip().buffer().use { it.write(byteArray) } - - return newFile.uri.toString() - } else { - val file = UniFile.fromUri(context, uri) - ?: throw Exception("Couldn't create backup file") - val byteArray = parser.encodeToByteArray(BackupSerializer, backup!!) - file.openOutputStream().sink().gzip().buffer().use { it.write(byteArray) } - - return file.uri.toString() - } + val byteArray = parser.encodeToByteArray(BackupSerializer, backup!!) + file.openOutputStream().sink().gzip().buffer().use { it.write(byteArray) } + return file.uri.toString() } catch (e: Exception) { Timber.e(e) throw e } } - private fun getDatabaseManga() = getFavoriteManga() - private fun backupManga(mangas: List, flags: Int): List { return mangas.map { backupMangaObject(it, flags) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt index 8e0d3e6b2..6748e42e8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt @@ -3,12 +3,12 @@ package eu.kanade.tachiyomi.data.backup.full import android.content.Context import android.net.Uri import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.backup.AbstractBackupRestore import eu.kanade.tachiyomi.data.backup.BackupNotifier import eu.kanade.tachiyomi.data.backup.full.models.BackupCategory import eu.kanade.tachiyomi.data.backup.full.models.BackupHistory import eu.kanade.tachiyomi.data.backup.full.models.BackupManga import eu.kanade.tachiyomi.data.backup.full.models.BackupSerializer -import eu.kanade.tachiyomi.data.backup.models.AbstractBackupRestore import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Track diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestoreValidator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestoreValidator.kt index 3f47d8cae..e482196ba 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestoreValidator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestoreValidator.kt @@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.data.backup.full import android.content.Context import android.net.Uri import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.backup.AbstractBackupRestoreValidator import eu.kanade.tachiyomi.data.backup.full.models.BackupSerializer -import eu.kanade.tachiyomi.data.backup.models.AbstractBackupRestoreValidator import kotlinx.serialization.ExperimentalSerializationApi import okio.buffer import okio.gzip diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt index 0c33a172a..76eb73999 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt @@ -12,6 +12,7 @@ import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject import com.hippo.unifile.UniFile +import eu.kanade.tachiyomi.data.backup.AbstractBackupManager import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY_MASK import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CHAPTER @@ -34,7 +35,6 @@ import eu.kanade.tachiyomi.data.backup.legacy.serializer.ChapterTypeAdapter import eu.kanade.tachiyomi.data.backup.legacy.serializer.HistoryTypeAdapter import eu.kanade.tachiyomi.data.backup.legacy.serializer.MangaTypeAdapter import eu.kanade.tachiyomi.data.backup.legacy.serializer.TrackTypeAdapter -import eu.kanade.tachiyomi.data.backup.models.AbstractBackupManager import eu.kanade.tachiyomi.data.database.models.CategoryImpl import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.ChapterImpl @@ -108,7 +108,6 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab root[EXTENSIONS] = extensionEntries databaseHelper.inTransaction { - // Get manga from database val mangas = getFavoriteManga() val extensions: MutableSet = mutableSetOf() @@ -135,39 +134,33 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab } try { - // When BackupCreatorJob - if (isJob) { - // Get dir of file and create - var dir = UniFile.fromUri(context, uri) - dir = dir.createDirectory("automatic") + val file: UniFile = ( + if (isJob) { + // Get dir of file and create + var dir = UniFile.fromUri(context, uri) + dir = dir.createDirectory("automatic") - // Delete older backups - val numberOfBackups = numberOfBackups() - val backupRegex = Regex("""tachiyomi_\d+-\d+-\d+_\d+-\d+.json""") - dir.listFiles { _, filename -> backupRegex.matches(filename) } - .orEmpty() - .sortedByDescending { it.name } - .drop(numberOfBackups - 1) - .forEach { it.delete() } + // Delete older backups + val numberOfBackups = numberOfBackups() + val backupRegex = Regex("""tachiyomi_\d+-\d+-\d+_\d+-\d+.json""") + dir.listFiles { _, filename -> backupRegex.matches(filename) } + .orEmpty() + .sortedByDescending { it.name } + .drop(numberOfBackups - 1) + .forEach { it.delete() } - // Create new file to place backup - val newFile = dir.createFile(Backup.getDefaultFilename()) - ?: throw Exception("Couldn't create backup file") - - newFile.openOutputStream().bufferedWriter().use { - parser.toJson(root, it) + // Create new file to place backup + dir.createFile(Backup.getDefaultFilename()) + } else { + UniFile.fromUri(context, uri) } + ) + ?: throw Exception("Couldn't create backup file") - return newFile.uri.toString() - } else { - val file = UniFile.fromUri(context, uri) - ?: throw Exception("Couldn't create backup file") - file.openOutputStream().bufferedWriter().use { - parser.toJson(root, it) - } - - return file.uri.toString() + file.openOutputStream().bufferedWriter().use { + parser.toJson(root, it) } + return file.uri.toString() } catch (e: Exception) { Timber.e(e) throw e diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt index 0efea6220..1aaabbd44 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt @@ -9,12 +9,12 @@ import com.google.gson.JsonObject import com.google.gson.JsonParser import com.google.gson.stream.JsonReader import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.backup.AbstractBackupRestore import eu.kanade.tachiyomi.data.backup.BackupConst import eu.kanade.tachiyomi.data.backup.BackupNotifier import eu.kanade.tachiyomi.data.backup.legacy.models.Backup import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.MANGAS import eu.kanade.tachiyomi.data.backup.legacy.models.DHistory -import eu.kanade.tachiyomi.data.backup.models.AbstractBackupRestore import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.ChapterImpl import eu.kanade.tachiyomi.data.database.models.Manga diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestoreValidator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestoreValidator.kt index 70f05aa30..f1b7cbf12 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestoreValidator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestoreValidator.kt @@ -6,8 +6,8 @@ import com.google.gson.JsonObject import com.google.gson.JsonParser import com.google.gson.stream.JsonReader import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.backup.AbstractBackupRestoreValidator import eu.kanade.tachiyomi.data.backup.legacy.models.Backup -import eu.kanade.tachiyomi.data.backup.models.AbstractBackupRestoreValidator class LegacyBackupRestoreValidator : AbstractBackupRestoreValidator() { /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index 4c43963f1..a93b233b9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -156,89 +156,74 @@ class SettingsBackupController : SettingsController() { } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - when (requestCode) { - CODE_BACKUP_DIR -> if (data != null && resultCode == Activity.RESULT_OK) { - val activity = activity ?: return - // Get uri of backup folder. - val uri = data.data + if (data != null && resultCode == Activity.RESULT_OK) { + val activity = activity ?: return + val uri = data.data - // Get UriPermission so it's possible to write files - val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION + when (requestCode) { + CODE_BACKUP_DIR -> { + // Get UriPermission so it's possible to write files + val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION - if (uri != null) { - activity.contentResolver.takePersistableUriPermission(uri, flags) + if (uri != null) { + activity.contentResolver.takePersistableUriPermission(uri, flags) + } + + // Set backup Uri + preferences.backupsDirectory().set(uri.toString()) } + CODE_FULL_BACKUP_CREATE, CODE_LEGACY_BACKUP_CREATE -> { + val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION - // Set backup Uri - preferences.backupsDirectory().set(uri.toString()) - } - CODE_LEGACY_BACKUP_CREATE -> if (data != null && resultCode == Activity.RESULT_OK) { - val activity = activity ?: return + if (uri != null) { + activity.contentResolver.takePersistableUriPermission(uri, flags) + } - val uri = data.data - val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION + val file = UniFile.fromUri(activity, uri) - if (uri != null) { - activity.contentResolver.takePersistableUriPermission(uri, flags) + activity.toast(R.string.creating_backup) + + BackupCreateService.start( + activity, + file.uri, + backupFlags, + if (requestCode == CODE_FULL_BACKUP_CREATE) BackupConst.BACKUP_TYPE_FULL else BackupConst.BACKUP_TYPE_LEGACY + ) } - - val file = UniFile.fromUri(activity, uri) - - activity.toast(R.string.creating_backup) - - BackupCreateService.start(activity, file.uri, backupFlags, BackupConst.BACKUP_TYPE_LEGACY) - } - CODE_BACKUP_RESTORE -> if (data != null && resultCode == Activity.RESULT_OK) { - val uri = data.data - if (uri?.path != null) { - if (uri.path!!.endsWith(".proto.gz")) { - val options = arrayOf( - R.string.full_restore_offline, - R.string.full_restore_online - ) - .map { activity!!.getString(it) } - MaterialDialog(activity!!) - .title(R.string.full_restore_mode) - .listItemsSingleChoice( - items = options, - initialSelection = 0 - ) { _, index, _ -> - RestoreBackupDialog( - uri, - BackupConst.BACKUP_TYPE_FULL, - isOnline = index != 0 - ).showDialog(router) - } - .positiveButton(R.string.action_restore) - .show() - } else if (uri.path!!.endsWith(".json")) { - RestoreBackupDialog( - uri, - BackupConst.BACKUP_TYPE_LEGACY, - isOnline = true - ).showDialog(router) + CODE_BACKUP_RESTORE -> { + if (uri?.path != null) { + if (uri.path!!.endsWith(".proto.gz")) { + val options = arrayOf( + R.string.full_restore_offline, + R.string.full_restore_online + ) + .map { activity.getString(it) } + MaterialDialog(activity) + .title(R.string.full_restore_mode) + .listItemsSingleChoice( + items = options, + initialSelection = 0 + ) { _, index, _ -> + RestoreBackupDialog( + uri, + BackupConst.BACKUP_TYPE_FULL, + isOnline = index != 0 + ).showDialog(router) + } + .positiveButton(R.string.action_restore) + .show() + } else if (uri.path!!.endsWith(".json")) { + RestoreBackupDialog( + uri, + BackupConst.BACKUP_TYPE_LEGACY, + isOnline = true + ).showDialog(router) + } } } } - CODE_FULL_BACKUP_CREATE -> if (data != null && resultCode == Activity.RESULT_OK) { - val activity = activity ?: return - - val uri = data.data - val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION - - if (uri != null) { - activity.contentResolver.takePersistableUriPermission(uri, flags) - } - - val file = UniFile.fromUri(activity, uri) - - activity.toast(R.string.creating_backup) - - BackupCreateService.start(activity, file.uri, backupFlags, BackupConst.BACKUP_TYPE_FULL) - } } } @@ -268,10 +253,16 @@ class SettingsBackupController : SettingsController() { fun createBackup(flags: Int, type: Int) { backupFlags = flags val currentDir = preferences.backupsDirectory().get() - val code = if (type == BackupConst.BACKUP_TYPE_FULL) CODE_FULL_BACKUP_CREATE else CODE_LEGACY_BACKUP_CREATE + val code = when (type) { + BackupConst.BACKUP_TYPE_FULL -> CODE_FULL_BACKUP_CREATE + else -> CODE_LEGACY_BACKUP_CREATE + } + val fileName = when (type) { + BackupConst.BACKUP_TYPE_FULL -> BackupFull.getDefaultFilename() + else -> Backup.getDefaultFilename() + } try { - val fileName = if (type == BackupConst.BACKUP_TYPE_FULL) BackupFull.getDefaultFilename() else Backup.getDefaultFilename() // Use Android's built-in file creator val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) .addCategory(Intent.CATEGORY_OPENABLE)