Remove manga from trackers (#9535)

* Dialog for service tracker removal added, anilist query prepared

* added API delete requests for Mal and Kitsu

* implement and fix tracker delete for anilist, shikimori, mangaupdates

* implement and test mal delete request

* Update to dialog text to reflect current tracker

* finish kitsu api request and block bangumi tracker removal

* Change delete flag into interface, localise strings, clean up logs

* Add shikimori delete compatibility for already existing entries

* update track delete dialog prompt to include checkbox, update strings

* Update i18n/src/main/res/values/strings.xml

Co-authored-by: stevenyomi <95685115+stevenyomi@users.noreply.github.com>

* Update i18n/src/main/res/values/strings.xml

---------

Co-authored-by: unknown <zaghdane@fireflow.de>
Co-authored-by: arkon <arkon@users.noreply.github.com>
Co-authored-by: stevenyomi <95685115+stevenyomi@users.noreply.github.com>
This commit is contained in:
zaghdaneh
2023-06-23 04:06:43 +02:00
committed by GitHub
parent 7f0ed58b54
commit b36b3bfcab
13 changed files with 258 additions and 24 deletions
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.manga.track
import android.app.Application
import android.content.Context
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
@@ -11,6 +12,7 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@@ -48,6 +50,7 @@ import eu.kanade.presentation.track.TrackServiceSearch
import eu.kanade.presentation.track.TrackStatusSelector
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.DeletableTrackService
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
@@ -157,7 +160,16 @@ data class TrackInfoDialogHomeScreen(
}
},
onOpenInBrowser = { openTrackerInBrowser(context, it) },
) { sm.unregisterTracking(it.service.id) }
onRemoved = {
navigator.push(
TrackServiceRemoveScreen(
mangaId = mangaId,
track = it.track!!,
serviceId = it.service.id,
),
)
},
)
}
/**
@@ -174,7 +186,6 @@ data class TrackInfoDialogHomeScreen(
private val mangaId: Long,
private val sourceId: Long,
private val getTracks: GetTracks = Injekt.get(),
private val deleteTrack: DeleteTrack = Injekt.get(),
) : StateScreenModel<Model.State>(State()) {
init {
@@ -204,10 +215,6 @@ data class TrackInfoDialogHomeScreen(
}
}
fun unregisterTracking(serviceId: Long) {
coroutineScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) }
}
private suspend fun refreshTrackers() {
val insertTrack = Injekt.get<InsertTrack>()
val getMangaWithChapters = Injekt.get<GetMangaWithChapters>()
@@ -723,3 +730,100 @@ data class TrackServiceSearchScreen(
)
}
}
private data class TrackServiceRemoveScreen(
private val mangaId: Long,
private val track: Track,
private val serviceId: Long,
) : Screen() {
@Composable
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
val sm = rememberScreenModel {
Model(
mangaId = mangaId,
track = track,
service = Injekt.get<TrackManager>().getService(serviceId)!!,
)
}
val serviceName = stringResource(sm.getServiceNameRes())
var removeRemoteTrack by remember { mutableStateOf(false) }
AlertDialogContent(
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
icon = {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
)
},
title = {
Text(
text = stringResource(R.string.track_delete_title, serviceName),
textAlign = TextAlign.Center,
)
},
text = {
Column {
Text(
text = stringResource(R.string.track_delete_text, serviceName),
)
if (sm.isServiceDeletable()) {
Row(verticalAlignment = Alignment.CenterVertically) {
Checkbox(checked = removeRemoteTrack, onCheckedChange = { removeRemoteTrack = it })
Text(text = stringResource(R.string.track_delete_remote_text, serviceName))
}
}
}
},
buttons = {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(
MaterialTheme.padding.small,
Alignment.End,
),
) {
TextButton(onClick = navigator::pop) {
Text(text = stringResource(R.string.action_cancel))
}
FilledTonalButton(
onClick = {
sm.unregisterTracking(serviceId)
if (removeRemoteTrack) sm.deleteMangaFromService()
navigator.pop()
},
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.onErrorContainer,
),
) {
Text(text = stringResource(R.string.action_ok))
}
}
},
)
}
private class Model(
private val mangaId: Long,
private val track: Track,
private val service: TrackService,
private val deleteTrack: DeleteTrack = Injekt.get(),
) : ScreenModel {
fun getServiceNameRes() = service.nameRes()
fun isServiceDeletable() = service is DeletableTrackService
fun deleteMangaFromService() {
coroutineScope.launchNonCancellable {
(service as DeletableTrackService).delete(track.toDbTrack())
}
}
fun unregisterTracking(serviceId: Long) {
coroutineScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) }
}
}
}