Combine global update item restrictions

(cherry picked from commit 818fe50f7772e42bff710b471bb0f687ab58ee10)

# Conflicts:
#	app/build.gradle.kts
#	app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt
This commit is contained in:
arkon 2021-12-17 09:57:37 -05:00 committed by Jobobby04
parent a9bb01125e
commit b19c178eae
12 changed files with 115 additions and 78 deletions

View File

@ -32,7 +32,7 @@ android {
applicationId = "eu.kanade.tachiyomi.sy"
minSdk = AndroidConfig.minSdk
targetSdk = AndroidConfig.targetSdk
versionCode = 22
versionCode = 23
versionName = "1.7.0"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")

View File

@ -5,8 +5,10 @@ import androidx.core.content.edit
import androidx.preference.PreferenceManager
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.MANGA_ONGOING
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.minusAssign
import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
@ -52,6 +54,8 @@ object Migrations {
return false
}
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
if (oldVersion < 14) {
// Restore jobs after upgrading to Evernote's job scheduler.
if (BuildConfig.INCLUDE_UPDATER) {
@ -98,8 +102,6 @@ object Migrations {
}
if (oldVersion < 44) {
// Reset sorting preference if using removed sort by source
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val oldSortingMode = prefs.getInt(PreferenceKeys.librarySortingMode, 0)
@Suppress("DEPRECATION")
@ -111,7 +113,6 @@ object Migrations {
}
if (oldVersion < 52) {
// Migrate library filters to tri-state versions
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
fun convertBooleanPrefToTriState(key: String): Int {
val oldPrefValue = prefs.getBoolean(key, false)
return if (oldPrefValue) ExtendedNavigationView.Item.TriStateGroup.State.INCLUDE.value
@ -140,7 +141,6 @@ object Migrations {
}
if (oldVersion < 57) {
// Migrate DNS over HTTPS setting
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val wasDohEnabled = prefs.getBoolean("enable_doh", false)
if (wasDohEnabled) {
prefs.edit {
@ -151,7 +151,6 @@ object Migrations {
}
if (oldVersion < 59) {
// Reset rotation to Free after replacing Lock
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
if (prefs.contains("pref_rotation_type_key")) {
prefs.edit {
putInt("pref_rotation_type_key", 1)
@ -170,7 +169,6 @@ object Migrations {
}
// Migrate Rotation and Viewer values to default values for viewer_flags
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val newOrientation = when (prefs.getInt("pref_rotation_type_key", 1)) {
1 -> OrientationType.FREE.flagValue
2 -> OrientationType.PORTRAIT.flagValue
@ -199,8 +197,6 @@ object Migrations {
}
}
if (oldVersion < 64) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val oldSortingMode = prefs.getInt(PreferenceKeys.librarySortingMode, 0)
val oldSortingDirection = prefs.getBoolean(PreferenceKeys.librarySortingDirection, true)
@ -245,6 +241,12 @@ object Migrations {
LibraryUpdateJob.setupTask(context, 12)
}
}
if (oldVersion < 72) {
val oldUpdateOngoingOnly = prefs.getBoolean("pref_update_only_non_completed_key", true)
if (!oldUpdateOngoingOnly) {
preferences.libraryUpdateMangaRestriction() -= MANGA_ONGOING
}
}
return true
}

View File

@ -8,8 +8,8 @@ import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import eu.kanade.tachiyomi.data.preference.CHARGING
import eu.kanade.tachiyomi.data.preference.ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.system.isConnectedToWifi
import uy.kohesive.injekt.Injekt
@ -39,10 +39,10 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
val preferences = Injekt.get<PreferencesHelper>()
val interval = prefInterval ?: preferences.libraryUpdateInterval().get()
if (interval > 0) {
val restrictions = preferences.libraryUpdateRestriction().get()
val restrictions = preferences.libraryUpdateDeviceRestriction().get()
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresCharging(CHARGING in restrictions)
.setRequiresCharging(DEVICE_CHARGING in restrictions)
.build()
val request = PeriodicWorkRequestBuilder<LibraryUpdateJob>(
@ -62,8 +62,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
}
fun requiresWifiConnection(preferences: PreferencesHelper): Boolean {
val restrictions = preferences.libraryUpdateRestriction().get()
return ONLY_ON_WIFI in restrictions
val restrictions = preferences.libraryUpdateDeviceRestriction().get()
return DEVICE_ONLY_ON_WIFI in restrictions
}
}
}

View File

@ -20,7 +20,9 @@ import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.library.LibraryUpdateRanker.rankingScheme
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.MANGA_FULLY_READ
import eu.kanade.tachiyomi.data.preference.MANGA_ONGOING
import eu.kanade.tachiyomi.data.preference.PreferenceValues.GroupLibraryMode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
import eu.kanade.tachiyomi.data.track.TrackManager
@ -284,7 +286,11 @@ class LibraryUpdateService(
var listToUpdate = if (categoryId != -1) {
libraryManga.filter { it.category == categoryId }
// SY -->
} else if (group == LibraryGroup.BY_DEFAULT || groupLibraryUpdateType == PreferenceValues.GroupLibraryMode.GLOBAL || (groupLibraryUpdateType == PreferenceValues.GroupLibraryMode.ALL_BUT_UNGROUPED && group == LibraryGroup.UNGROUPED)) {
} else if (
group == LibraryGroup.BY_DEFAULT ||
groupLibraryUpdateType == GroupLibraryMode.GLOBAL ||
(groupLibraryUpdateType == GroupLibraryMode.ALL_BUT_UNGROUPED && group == LibraryGroup.UNGROUPED)
) {
val categoriesToUpdate = preferences.libraryUpdateCategories().get().map(String::toInt)
val listToInclude = if (categoriesToUpdate.isNotEmpty()) {
libraryManga.filter { it.category in categoriesToUpdate }
@ -294,9 +300,9 @@ class LibraryUpdateService(
val categoriesToExclude = preferences.libraryUpdateCategoriesExclude().get().map(String::toInt)
val listToExclude = if (categoriesToExclude.isNotEmpty()) {
libraryManga.filter { it.category in categoriesToExclude }
libraryManga.filter { it.category in categoriesToExclude }.toSet()
} else {
emptyList()
emptySet()
}
listToInclude.minus(listToExclude)
@ -337,12 +343,15 @@ class LibraryUpdateService(
}
// SY <--
}
if (target == Target.CHAPTERS && preferences.updateOnlyNonCompleted()) {
listToUpdate = listToUpdate.filterNot { it.status == SManga.COMPLETED }
}
if (target == Target.CHAPTERS && preferences.updateOnlyCompletelyRead()) {
listToUpdate = listToUpdate.filter { it.unread == 0 }
if (target == Target.CHAPTERS) {
val restrictions = preferences.libraryUpdateMangaRestriction().get()
if (MANGA_ONGOING in restrictions) {
listToUpdate = listToUpdate.filterNot { it.status == SManga.COMPLETED }
}
if (MANGA_FULLY_READ in restrictions) {
listToUpdate = listToUpdate.filter { it.unread == 0 }
}
}
val selectedScheme = preferences.libraryUpdatePrioritization().get()

View File

@ -101,10 +101,6 @@ object PreferenceKeys {
const val jumpToChapters = "jump_to_chapters"
const val updateOnlyNonCompleted = "pref_update_only_non_completed_key"
const val updateOnlyCompletelyRead = "pref_update_only_completely_read"
const val autoUpdateTrack = "pref_auto_update_manga_sync_key"
const val lastUsedSource = "last_catalogue_source"
@ -135,7 +131,8 @@ object PreferenceKeys {
const val libraryUpdateInterval = "pref_library_update_interval_key"
const val libraryUpdateRestriction = "library_update_restriction"
const val libraryUpdateDeviceRestriction = "library_update_restriction"
const val libraryUpdateMangaRestriction = "library_update_manga_restriction"
const val showUpdatesNavBadge = "library_update_show_tab_badge"

View File

@ -2,8 +2,11 @@ package eu.kanade.tachiyomi.data.preference
import eu.kanade.tachiyomi.R
const val ONLY_ON_WIFI = "wifi"
const val CHARGING = "ac"
const val DEVICE_ONLY_ON_WIFI = "wifi"
const val DEVICE_CHARGING = "ac"
const val MANGA_ONGOING = "manga_ongoing"
const val MANGA_FULLY_READ = "manga_fully_read"
/**
* This class stores the values for the preferences in the application.

View File

@ -181,10 +181,6 @@ class PreferencesHelper(val context: Context) {
fun jumpToChapters() = prefs.getBoolean(Keys.jumpToChapters, false)
fun updateOnlyNonCompleted() = prefs.getBoolean(Keys.updateOnlyNonCompleted, true)
fun updateOnlyCompletelyRead() = prefs.getBoolean(Keys.updateOnlyCompletelyRead, true)
fun autoUpdateTrack() = prefs.getBoolean(Keys.autoUpdateTrack, true)
fun lastUsedSource() = flowPrefs.getLong(Keys.lastUsedSource, -1)
@ -241,7 +237,8 @@ class PreferencesHelper(val context: Context) {
fun libraryUpdateInterval() = flowPrefs.getInt(Keys.libraryUpdateInterval, 24)
fun libraryUpdateRestriction() = flowPrefs.getStringSet(Keys.libraryUpdateRestriction, setOf(ONLY_ON_WIFI))
fun libraryUpdateDeviceRestriction() = flowPrefs.getStringSet(Keys.libraryUpdateDeviceRestriction, setOf(DEVICE_ONLY_ON_WIFI))
fun libraryUpdateMangaRestriction() = flowPrefs.getStringSet(Keys.libraryUpdateMangaRestriction, setOf(MANGA_FULLY_READ, MANGA_ONGOING))
fun showUpdatesNavBadge() = flowPrefs.getBoolean(Keys.showUpdatesNavBadge, false)
fun unreadUpdatesCount() = flowPrefs.getInt("library_unread_updates_count", 0)

View File

@ -17,8 +17,8 @@ import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.CHARGING
import eu.kanade.tachiyomi.data.preference.ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding
@ -444,15 +444,15 @@ class SettingsEhController : SettingsController() {
key = PreferenceKeys.eh_autoUpdateRestrictions
titleRes = R.string.auto_update_restrictions
entriesRes = arrayOf(R.string.connected_to_wifi, R.string.charging)
entryValues = arrayOf(ONLY_ON_WIFI, CHARGING)
entryValues = arrayOf(DEVICE_ONLY_ON_WIFI, DEVICE_CHARGING)
fun updateSummary() {
val restrictions = preferences.exhAutoUpdateRequirements().get()
.sorted()
.map {
when (it) {
ONLY_ON_WIFI -> context.getString(R.string.connected_to_wifi)
CHARGING -> context.getString(R.string.charging)
DEVICE_ONLY_ON_WIFI -> context.getString(R.string.connected_to_wifi)
DEVICE_CHARGING -> context.getString(R.string.charging)
else -> it
}
}

View File

@ -11,9 +11,11 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.CHARGING
import eu.kanade.tachiyomi.data.preference.ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.MANGA_FULLY_READ
import eu.kanade.tachiyomi.data.preference.MANGA_ONGOING
import eu.kanade.tachiyomi.data.preference.PreferenceValues.GroupLibraryMode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.data.track.TrackManager
@ -182,11 +184,11 @@ class SettingsLibraryController : SettingsController() {
}
}
multiSelectListPreference {
key = Keys.libraryUpdateRestriction
key = Keys.libraryUpdateDeviceRestriction
titleRes = R.string.pref_library_update_restriction
entriesRes = arrayOf(R.string.connected_to_wifi, R.string.charging)
entryValues = arrayOf(ONLY_ON_WIFI, CHARGING)
defaultValue = setOf(ONLY_ON_WIFI)
entryValues = arrayOf(DEVICE_ONLY_ON_WIFI, DEVICE_CHARGING)
defaultValue = preferences.libraryUpdateDeviceRestriction().defaultValue
preferences.libraryUpdateInterval().asImmediateFlow { isVisible = it > 0 }
.launchIn(viewScope)
@ -198,12 +200,12 @@ class SettingsLibraryController : SettingsController() {
}
fun updateSummary() {
val restrictions = preferences.libraryUpdateRestriction().get()
val restrictions = preferences.libraryUpdateDeviceRestriction().get()
.sorted()
.map {
when (it) {
ONLY_ON_WIFI -> context.getString(R.string.connected_to_wifi)
CHARGING -> context.getString(R.string.charging)
DEVICE_ONLY_ON_WIFI -> context.getString(R.string.connected_to_wifi)
DEVICE_CHARGING -> context.getString(R.string.charging)
else -> it
}
}
@ -216,20 +218,42 @@ class SettingsLibraryController : SettingsController() {
summary = context.getString(R.string.restrictions, restrictionsText)
}
preferences.libraryUpdateRestriction().asFlow()
preferences.libraryUpdateDeviceRestriction().asFlow()
.onEach { updateSummary() }
.launchIn(viewScope)
}
switchPreference {
key = Keys.updateOnlyNonCompleted
titleRes = R.string.pref_update_only_non_completed
defaultValue = true
}
switchPreference {
key = Keys.updateOnlyCompletelyRead
titleRes = R.string.pref_update_only_completely_read
summaryRes = R.string.pref_update_only_completely_read_summary
defaultValue = false
multiSelectListPreference {
key = Keys.libraryUpdateMangaRestriction
titleRes = R.string.pref_library_update_manga_restriction
entriesRes = arrayOf(R.string.pref_update_only_completely_read, R.string.pref_update_only_non_completed)
entryValues = arrayOf(MANGA_FULLY_READ, MANGA_ONGOING)
defaultValue = preferences.libraryUpdateMangaRestriction().defaultValue
preferences.libraryUpdateInterval().asImmediateFlow { isVisible = it > 0 }
.launchIn(viewScope)
fun updateSummary() {
val restrictions = preferences.libraryUpdateMangaRestriction().get()
.sorted()
.map {
when (it) {
MANGA_ONGOING -> context.getString(R.string.pref_update_only_non_completed)
MANGA_FULLY_READ -> context.getString(R.string.pref_update_only_completely_read)
else -> it
}
}
val restrictionsText = if (restrictions.isEmpty()) {
context.getString(R.string.none)
} else {
restrictions.joinToString()
}
summary = context.getString(R.string.restrictions, restrictionsText)
}
preferences.libraryUpdateMangaRestriction().asFlow()
.onEach { updateSummary() }
.launchIn(viewScope)
}
preference {
key = Keys.libraryUpdateCategories
@ -281,11 +305,11 @@ class SettingsLibraryController : SettingsController() {
R.string.library_group_updates_all
)
entryValues = arrayOf(
PreferenceValues.GroupLibraryMode.GLOBAL.name,
PreferenceValues.GroupLibraryMode.ALL_BUT_UNGROUPED.name,
PreferenceValues.GroupLibraryMode.ALL.name
GroupLibraryMode.GLOBAL.name,
GroupLibraryMode.ALL_BUT_UNGROUPED.name,
GroupLibraryMode.ALL.name
)
defaultValue = PreferenceValues.GroupLibraryMode.GLOBAL.name
defaultValue = GroupLibraryMode.GLOBAL.name
summary = "%s"
}
// SY <--

View File

@ -16,8 +16,10 @@ import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.data.database.tables.TrackTable
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.MANGA_ONGOING
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.minusAssign
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
@ -83,6 +85,8 @@ object EXHMigrations {
if (oldVersion == 0) {
return false
}
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
if (oldVersion under 4) {
db.inTransaction {
updateSourceId(HBROWSE_SOURCE_ID, 6912)
@ -229,7 +233,6 @@ object EXHMigrations {
}
if (oldVersion under 14) {
// Migrate DNS over HTTPS setting
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val wasDohEnabled = prefs.getBoolean("enable_doh", false)
if (wasDohEnabled) {
prefs.edit {
@ -240,7 +243,6 @@ object EXHMigrations {
}
if (oldVersion under 16) {
// Reset rotation to Free after replacing Lock
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
if (prefs.contains("pref_rotation_type_key")) {
prefs.edit {
putInt("pref_rotation_type_key", 1)
@ -253,7 +255,6 @@ object EXHMigrations {
}
if (oldVersion under 17) {
// Migrate Rotation and Viewer values to default values for viewer_flags
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val newOrientation = when (prefs.getInt("pref_rotation_type_key", 1)) {
1 -> OrientationType.FREE.flagValue
2 -> OrientationType.PORTRAIT.flagValue
@ -294,8 +295,6 @@ object EXHMigrations {
}
}
if (oldVersion under 20) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val oldSortingMode = prefs.getInt(PreferenceKeys.librarySortingMode, 0)
val oldSortingDirection = prefs.getBoolean(PreferenceKeys.librarySortingDirection, true)
@ -345,6 +344,12 @@ object EXHMigrations {
LibraryUpdateJob.setupTask(context, 12)
}
}
if (oldVersion under 23) {
val oldUpdateOngoingOnly = prefs.getBoolean("pref_update_only_non_completed_key", true)
if (!oldUpdateOngoingOnly) {
preferences.libraryUpdateMangaRestriction() -= MANGA_ONGOING
}
}
// if (oldVersion under 1) { } (1 is current release version)
// do stuff here when releasing changed crap

View File

@ -16,8 +16,8 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.library.LibraryUpdateNotifier
import eu.kanade.tachiyomi.data.preference.CHARGING
import eu.kanade.tachiyomi.data.preference.ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.toSChapter
@ -245,7 +245,7 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara
val interval = prefInterval ?: preferences.exhAutoUpdateFrequency().get()
if (interval > 0) {
val restrictions = preferences.exhAutoUpdateRequirements().get()
val acRestriction = CHARGING in restrictions
val acRestriction = DEVICE_CHARGING in restrictions
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
@ -276,7 +276,7 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara
fun requiresWifiConnection(preferences: PreferencesHelper): Boolean {
val restrictions = preferences.exhAutoUpdateRequirements().get()
return ONLY_ON_WIFI in restrictions
return DEVICE_ONLY_ON_WIFI in restrictions
}
}

View File

@ -217,13 +217,13 @@
<string name="update_72hour">Every 3 days</string>
<string name="update_weekly">Weekly</string>
<string name="pref_library_update_prioritization">Update order</string>
<string name="pref_library_update_restriction">Update restrictions</string>
<string name="pref_library_update_restriction">Device restrictions</string>
<string name="connected_to_wifi">Only on Wi-Fi</string>
<string name="charging">Charging</string>
<string name="restrictions">Restrictions: %s</string>
<string name="pref_update_only_non_completed">Only update ongoing manga</string>
<string name="pref_update_only_completely_read">Only update completely read manga</string>
<string name="pref_update_only_completely_read_summary">Only update manga if there is no unread chapter(completely read)</string>
<string name="pref_library_update_manga_restriction">Manga restrictions</string>
<string name="pref_update_only_completely_read">Completely read</string>
<string name="pref_update_only_non_completed">Ongoing</string>
<string name="pref_library_update_show_tab_badge">Show unread count on Updates icon</string>
<string name="pref_library_update_refresh_metadata">Automatically refresh metadata</string>
<string name="pref_library_update_refresh_metadata_summary">Check for new cover and details when updating library</string>