mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Cleanup
This commit is contained in:
parent
7e4cc175de
commit
01ce26003d
7 changed files with 71 additions and 76 deletions
|
@ -26,8 +26,6 @@ import com.lagradost.nicehttp.RequestBodyTypes
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.json.JSONException
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
@ -1249,12 +1247,8 @@ interface LoadResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LoadResponse.getImdbId(): String? {
|
fun LoadResponse.getImdbId(): String? {
|
||||||
val simklId = this.syncData[simklIdPrefix] ?: return null
|
return normalSafeApiCall {
|
||||||
return try {
|
SimklApi.readIdFromString(this.syncData[simklIdPrefix])?.get(SimklApi.Companion.SyncServices.Imdb)
|
||||||
val jsonObject = JSONObject(simklId)
|
|
||||||
jsonObject.optString("Imdb")
|
|
||||||
} catch (e: JSONException) {
|
|
||||||
null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,7 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read the id string to get all other ids */
|
/** Read the id string to get all other ids */
|
||||||
private fun readIdFromString(idString: String?): Map<SyncServices, String> {
|
fun readIdFromString(idString: String?): Map<SyncServices, String> {
|
||||||
return tryParseJson(idString) ?: return emptyMap()
|
return tryParseJson(idString) ?: return emptyMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -361,7 +361,8 @@ class HomeParentItemAdapterPreview(
|
||||||
fab.context,
|
fab.context,
|
||||||
item
|
item
|
||||||
) { statusChanged: Boolean ->
|
) { statusChanged: Boolean ->
|
||||||
if (statusChanged) {
|
if (!statusChanged) return@updateWatchStatus
|
||||||
|
|
||||||
homePreviewBookmark.setCompoundDrawablesWithIntrinsicBounds(
|
homePreviewBookmark.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
null,
|
null,
|
||||||
ContextCompat.getDrawable(
|
ContextCompat.getDrawable(
|
||||||
|
@ -377,7 +378,6 @@ class HomeParentItemAdapterPreview(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun onViewDetachedFromWindow() {
|
fun onViewDetachedFromWindow() {
|
||||||
previewViewpager.unregisterOnPageChangeCallback(previewCallback)
|
previewViewpager.unregisterOnPageChangeCallback(previewCallback)
|
||||||
|
|
|
@ -74,17 +74,17 @@ class HomeViewModel : ViewModel() {
|
||||||
val watchPos = getViewPos(resume.episodeId)
|
val watchPos = getViewPos(resume.episodeId)
|
||||||
|
|
||||||
DataStoreHelper.ResumeWatchingResult(
|
DataStoreHelper.ResumeWatchingResult(
|
||||||
watchPos,
|
|
||||||
resume.parentId,
|
|
||||||
resume.episode,
|
|
||||||
resume.season,
|
|
||||||
resume.isFromDownload,
|
|
||||||
resume.episodeId,
|
|
||||||
data.name,
|
data.name,
|
||||||
data.url,
|
data.url,
|
||||||
data.apiName,
|
data.apiName,
|
||||||
data.type,
|
data.type,
|
||||||
data.poster
|
data.poster,
|
||||||
|
watchPos,
|
||||||
|
resume.episodeId,
|
||||||
|
resume.parentId,
|
||||||
|
resume.episode,
|
||||||
|
resume.season,
|
||||||
|
resume.isFromDownload
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,10 +54,10 @@ import com.lagradost.cloudstream3.utils.Coroutines.ioWork
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe
|
import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.deleteBookmarkedData
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.deleteBookmarkedData
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllBookmarkedDataByWatchType
|
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllFavorites
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllFavorites
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllSubscriptions
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllSubscriptions
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedDataByWatchType
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getDub
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getDub
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getFavoritesData
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getFavoritesData
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getLastWatched
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getLastWatched
|
||||||
|
@ -832,7 +832,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
response.name,
|
response.name,
|
||||||
response.year,
|
response.year,
|
||||||
response.getImdbId(),
|
response.getImdbId(),
|
||||||
getAllBookmarkedDataByWatchType()[status] ?: emptyList()
|
getBookmarkedDataByWatchType(status)
|
||||||
) { shouldContinue: Boolean, duplicateId: Int? ->
|
) { shouldContinue: Boolean, duplicateId: Int? ->
|
||||||
if (!shouldContinue) return@checkAndWarnDuplicates
|
if (!shouldContinue) return@checkAndWarnDuplicates
|
||||||
|
|
||||||
|
@ -841,20 +841,21 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
setResultWatchState(currentId, status.internalId)
|
setResultWatchState(currentId, status.internalId)
|
||||||
|
|
||||||
val current = getBookmarkedData(currentId)
|
val current = getBookmarkedData(currentId)
|
||||||
val currentTime = System.currentTimeMillis()
|
|
||||||
setBookmarkedData(
|
setBookmarkedData(
|
||||||
currentId,
|
currentId,
|
||||||
DataStoreHelper.BookmarkedData(
|
DataStoreHelper.BookmarkedData(
|
||||||
current?.bookmarkedTime ?: currentTime,
|
current?.bookmarkedTime ?: unixTimeMS,
|
||||||
currentTime,
|
|
||||||
currentId,
|
currentId,
|
||||||
|
unixTimeMS,
|
||||||
response.name,
|
response.name,
|
||||||
response.year,
|
|
||||||
response.url,
|
response.url,
|
||||||
response.apiName,
|
response.apiName,
|
||||||
response.type,
|
response.type,
|
||||||
response.posterUrl,
|
response.posterUrl,
|
||||||
|
response.year,
|
||||||
response.getImdbId()
|
response.getImdbId()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -920,15 +921,15 @@ class ResultViewModel2 : ViewModel() {
|
||||||
currentId,
|
currentId,
|
||||||
DataStoreHelper.SubscribedData(
|
DataStoreHelper.SubscribedData(
|
||||||
current?.subscribedTime ?: unixTimeMS,
|
current?.subscribedTime ?: unixTimeMS,
|
||||||
unixTimeMS,
|
|
||||||
response.getLatestEpisodes(),
|
response.getLatestEpisodes(),
|
||||||
currentId,
|
currentId,
|
||||||
|
unixTimeMS,
|
||||||
response.name,
|
response.name,
|
||||||
response.year,
|
|
||||||
response.url,
|
response.url,
|
||||||
response.apiName,
|
response.apiName,
|
||||||
response.type,
|
response.type,
|
||||||
response.posterUrl,
|
response.posterUrl,
|
||||||
|
response.year,
|
||||||
response.getImdbId()
|
response.getImdbId()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -983,14 +984,14 @@ class ResultViewModel2 : ViewModel() {
|
||||||
currentId,
|
currentId,
|
||||||
DataStoreHelper.FavoritesData(
|
DataStoreHelper.FavoritesData(
|
||||||
current?.favoritesTime ?: unixTimeMS,
|
current?.favoritesTime ?: unixTimeMS,
|
||||||
unixTimeMS,
|
|
||||||
currentId,
|
currentId,
|
||||||
|
unixTimeMS,
|
||||||
response.name,
|
response.name,
|
||||||
response.year,
|
|
||||||
response.url,
|
response.url,
|
||||||
response.apiName,
|
response.apiName,
|
||||||
response.type,
|
response.type,
|
||||||
response.posterUrl,
|
response.posterUrl,
|
||||||
|
response.year,
|
||||||
response.getImdbId()
|
response.getImdbId()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1010,7 +1011,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
name: String,
|
name: String,
|
||||||
year: Int?,
|
year: Int?,
|
||||||
imdbId: String?,
|
imdbId: String?,
|
||||||
data: List<DataStoreHelper.BaseSearchResponse>,
|
data: List<DataStoreHelper.LibrarySearchResponse>,
|
||||||
checkDuplicatesCallback: (shouldContinue: Boolean, duplicateId: Int?) -> Unit
|
checkDuplicatesCallback: (shouldContinue: Boolean, duplicateId: Int?) -> Unit
|
||||||
) {
|
) {
|
||||||
fun normalizeString(input: String): String {
|
fun normalizeString(input: String): String {
|
||||||
|
|
|
@ -352,34 +352,35 @@ object DataStoreHelper {
|
||||||
/**
|
/**
|
||||||
* Used to display notifications on new episodes and posters in library.
|
* Used to display notifications on new episodes and posters in library.
|
||||||
**/
|
**/
|
||||||
abstract class BaseSearchResponse(
|
abstract class LibrarySearchResponse(
|
||||||
@JsonProperty("id") override var id: Int?,
|
@JsonProperty("id") override var id: Int?,
|
||||||
|
@JsonProperty("latestUpdatedTime") open val latestUpdatedTime: Long,
|
||||||
@JsonProperty("name") override val name: String,
|
@JsonProperty("name") override val name: String,
|
||||||
@JsonProperty("year") open val year: Int?,
|
|
||||||
@JsonProperty("url") override val url: String,
|
@JsonProperty("url") override val url: String,
|
||||||
@JsonProperty("apiName") override val apiName: String,
|
@JsonProperty("apiName") override val apiName: String,
|
||||||
@JsonProperty("type") override var type: TvType? = null,
|
@JsonProperty("type") override var type: TvType?,
|
||||||
@JsonProperty("posterUrl") override var posterUrl: String?,
|
@JsonProperty("posterUrl") override var posterUrl: String?,
|
||||||
@JsonProperty("imdbId") open val imdbId: String? = null,
|
@JsonProperty("year") open val year: Int?,
|
||||||
@JsonProperty("quality") override var quality: SearchQuality? = null,
|
@JsonProperty("imdbId") open val imdbId: String?,
|
||||||
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>? = null
|
@JsonProperty("quality") override var quality: SearchQuality?,
|
||||||
|
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>?
|
||||||
) : SearchResponse
|
) : SearchResponse
|
||||||
|
|
||||||
data class SubscribedData(
|
data class SubscribedData(
|
||||||
@JsonProperty("subscribedTime") val subscribedTime: Long,
|
@JsonProperty("subscribedTime") val subscribedTime: Long,
|
||||||
@JsonProperty("latestUpdatedTime") val latestUpdatedTime: Long,
|
|
||||||
@JsonProperty("lastSeenEpisodeCount") val lastSeenEpisodeCount: Map<DubStatus, Int?>,
|
@JsonProperty("lastSeenEpisodeCount") val lastSeenEpisodeCount: Map<DubStatus, Int?>,
|
||||||
override var id: Int?,
|
override var id: Int?,
|
||||||
|
override val latestUpdatedTime: Long,
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val year: Int?,
|
|
||||||
override val url: String,
|
override val url: String,
|
||||||
override val apiName: String,
|
override val apiName: String,
|
||||||
override var type: TvType?,
|
override var type: TvType?,
|
||||||
override var posterUrl: String?,
|
override var posterUrl: String?,
|
||||||
override var imdbId: String? = null,
|
override val year: Int?,
|
||||||
|
override val imdbId: String?,
|
||||||
override var quality: SearchQuality? = null,
|
override var quality: SearchQuality? = null,
|
||||||
override var posterHeaders: Map<String, String>? = null
|
override var posterHeaders: Map<String, String>? = null
|
||||||
) : BaseSearchResponse(id, name, year, url, apiName, type, posterUrl, imdbId, quality, posterHeaders) {
|
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, imdbId, quality, posterHeaders) {
|
||||||
fun toLibraryItem(): SyncAPI.LibraryItem? {
|
fun toLibraryItem(): SyncAPI.LibraryItem? {
|
||||||
return SyncAPI.LibraryItem(
|
return SyncAPI.LibraryItem(
|
||||||
name,
|
name,
|
||||||
|
@ -396,18 +397,18 @@ object DataStoreHelper {
|
||||||
|
|
||||||
data class BookmarkedData(
|
data class BookmarkedData(
|
||||||
@JsonProperty("bookmarkedTime") val bookmarkedTime: Long,
|
@JsonProperty("bookmarkedTime") val bookmarkedTime: Long,
|
||||||
@JsonProperty("latestUpdatedTime") val latestUpdatedTime: Long,
|
|
||||||
override var id: Int?,
|
override var id: Int?,
|
||||||
|
override val latestUpdatedTime: Long,
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val year: Int?,
|
|
||||||
override val url: String,
|
override val url: String,
|
||||||
override val apiName: String,
|
override val apiName: String,
|
||||||
override var type: TvType?,
|
override var type: TvType?,
|
||||||
override var posterUrl: String?,
|
override var posterUrl: String?,
|
||||||
override var imdbId: String? = null,
|
override val year: Int?,
|
||||||
|
override val imdbId: String?,
|
||||||
override var quality: SearchQuality? = null,
|
override var quality: SearchQuality? = null,
|
||||||
override var posterHeaders: Map<String, String>? = null
|
override var posterHeaders: Map<String, String>? = null
|
||||||
) : BaseSearchResponse(id, name, year, url, apiName, type, posterUrl, imdbId, quality, posterHeaders) {
|
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, imdbId, quality, posterHeaders) {
|
||||||
fun toLibraryItem(id: String): SyncAPI.LibraryItem {
|
fun toLibraryItem(id: String): SyncAPI.LibraryItem {
|
||||||
return SyncAPI.LibraryItem(
|
return SyncAPI.LibraryItem(
|
||||||
name,
|
name,
|
||||||
|
@ -424,18 +425,18 @@ object DataStoreHelper {
|
||||||
|
|
||||||
data class FavoritesData(
|
data class FavoritesData(
|
||||||
@JsonProperty("favoritesTime") val favoritesTime: Long,
|
@JsonProperty("favoritesTime") val favoritesTime: Long,
|
||||||
@JsonProperty("latestUpdatedTime") val latestUpdatedTime: Long,
|
|
||||||
override var id: Int?,
|
override var id: Int?,
|
||||||
|
override val latestUpdatedTime: Long,
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val year: Int?,
|
|
||||||
override val url: String,
|
override val url: String,
|
||||||
override val apiName: String,
|
override val apiName: String,
|
||||||
override var type: TvType?,
|
override var type: TvType?,
|
||||||
override var posterUrl: String?,
|
override var posterUrl: String?,
|
||||||
override var imdbId: String? = null,
|
override val year: Int?,
|
||||||
|
override val imdbId: String?,
|
||||||
override var quality: SearchQuality? = null,
|
override var quality: SearchQuality? = null,
|
||||||
override var posterHeaders: Map<String, String>? = null
|
override var posterHeaders: Map<String, String>? = null
|
||||||
) : BaseSearchResponse(id, name, year, url, apiName, type, posterUrl, imdbId, quality, posterHeaders) {
|
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, imdbId, quality, posterHeaders) {
|
||||||
fun toLibraryItem(): SyncAPI.LibraryItem? {
|
fun toLibraryItem(): SyncAPI.LibraryItem? {
|
||||||
return SyncAPI.LibraryItem(
|
return SyncAPI.LibraryItem(
|
||||||
name,
|
name,
|
||||||
|
@ -451,20 +452,20 @@ object DataStoreHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ResumeWatchingResult(
|
data class ResumeWatchingResult(
|
||||||
|
@JsonProperty("name") override val name: String,
|
||||||
|
@JsonProperty("url") override val url: String,
|
||||||
|
@JsonProperty("apiName") override val apiName: String,
|
||||||
|
@JsonProperty("type") override var type: TvType? = null,
|
||||||
|
@JsonProperty("posterUrl") override var posterUrl: String?,
|
||||||
@JsonProperty("watchPos") val watchPos: PosDur?,
|
@JsonProperty("watchPos") val watchPos: PosDur?,
|
||||||
|
@JsonProperty("id") override var id: Int?,
|
||||||
@JsonProperty("parentId") val parentId: Int?,
|
@JsonProperty("parentId") val parentId: Int?,
|
||||||
@JsonProperty("episode") val episode: Int?,
|
@JsonProperty("episode") val episode: Int?,
|
||||||
@JsonProperty("season") val season: Int?,
|
@JsonProperty("season") val season: Int?,
|
||||||
@JsonProperty("isFromDownload") val isFromDownload: Boolean,
|
@JsonProperty("isFromDownload") val isFromDownload: Boolean,
|
||||||
override var id: Int?,
|
@JsonProperty("quality") override var quality: SearchQuality? = null,
|
||||||
override val name: String,
|
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>? = null,
|
||||||
override val url: String,
|
) : SearchResponse
|
||||||
override val apiName: String,
|
|
||||||
override var type: TvType?,
|
|
||||||
override var posterUrl: String?,
|
|
||||||
override var quality: SearchQuality? = null,
|
|
||||||
override var posterHeaders: Map<String, String>? = null
|
|
||||||
) : BaseSearchResponse(id, name, null, url, apiName, type, posterUrl, null, quality, posterHeaders)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A datastore wide account for future implementations of a multiple account system
|
* A datastore wide account for future implementations of a multiple account system
|
||||||
|
@ -588,15 +589,14 @@ object DataStoreHelper {
|
||||||
return getKey("$currentAccount/$RESULT_WATCH_STATE_DATA", id.toString())
|
return getKey("$currentAccount/$RESULT_WATCH_STATE_DATA", id.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllBookmarkedDataByWatchType(): Map<WatchType, List<BookmarkedData>> {
|
fun getBookmarkedDataByWatchType(watchType: WatchType): List<BookmarkedData> {
|
||||||
val allBookmarkedData: List<BookmarkedData> =
|
val allBookmarkedData: List<BookmarkedData> =
|
||||||
getKeys("$currentAccount/$RESULT_WATCH_STATE_DATA")?.mapNotNull {
|
getKeys("$currentAccount/$RESULT_WATCH_STATE_DATA")?.mapNotNull {
|
||||||
getKey(it)
|
getKey(it)
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
||||||
return allBookmarkedData
|
return allBookmarkedData
|
||||||
.groupBy { getResultWatchState(it.id ?: return emptyMap()) }
|
.filter { getResultWatchState(it.id ?: return emptyList()) == watchType }
|
||||||
.mapValues { it.value }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllSubscriptions(): List<SubscribedData> {
|
fun getAllSubscriptions(): List<SubscribedData> {
|
||||||
|
|
|
@ -694,24 +694,24 @@
|
||||||
<string name="action_add_to_favorites">Add to favorites</string>
|
<string name="action_add_to_favorites">Add to favorites</string>
|
||||||
<string name="action_remove_from_favorites">Remove from favorites</string>
|
<string name="action_remove_from_favorites">Remove from favorites</string>
|
||||||
|
|
||||||
<string name="duplicate_title">Possible Duplicate Found</string>
|
<string name="duplicate_title">Potential Duplicate Found</string>
|
||||||
<string name="duplicate_add">Add</string>
|
<string name="duplicate_add">Add</string>
|
||||||
<string name="duplicate_replace">Replace</string>
|
<string name="duplicate_replace">Replace</string>
|
||||||
<string name="duplicate_cancel" translatable="false">@string/sort_cancel</string>
|
<string name="duplicate_cancel" translatable="false">@string/sort_cancel</string>
|
||||||
<string name="duplicate_message_bookmarks">
|
<string name="duplicate_message_bookmarks">
|
||||||
A possible duplicate with the same title \'%s\' and watch status \'%s\' already exists in your library.
|
It appears that a potentially duplicate title \'%s\' with the watch status \'%s\' already exists in your library.
|
||||||
|
|
||||||
\n\nDo you want to still add this to item, replace the existing one, or cancel the action?
|
\n\nWould you like to add this item anyway, replace the existing one, or cancel the action?
|
||||||
</string>
|
</string>
|
||||||
<string name="duplicate_message_subscriptions">
|
<string name="duplicate_message_subscriptions">
|
||||||
A possible duplicate with the same title \'%s\' already exists in your subscriptions.
|
You are already subscribed to a title that appears to be a potential duplicate: \'%s.\'
|
||||||
|
|
||||||
\n\nDo you want to still subscribe to this item, replace the existing subscription, or cancel the action?
|
\n\nWould you like to add this subscription anyway, replace the existing one, or cancel the action?
|
||||||
</string>
|
</string>
|
||||||
<string name="duplicate_message_favorites">
|
<string name="duplicate_message_favorites">
|
||||||
A possible duplicate with the same title \'%s\' already exists in your favorites.
|
It seems that a potentially duplicate title \'%s\' is already in your favorites.
|
||||||
|
|
||||||
\n\nDo you want to still add this to item, replace the existing one, or cancel the action?
|
\n\nWould you like to add this item anyway, replace the existing one, or cancel the action?
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue