Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for tracker URLs inside mihon #469

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class UpdateManga(
genre = remoteManga.getGenres(),
thumbnailUrl = thumbnailUrl,
status = remoteManga.status.toLong(),
webUrls = remoteManga.getWebUrls(),
updateStrategy = remoteManga.update_strategy,
initialized = true,
),
Expand Down
19 changes: 18 additions & 1 deletion app/src/main/java/eu/kanade/domain/manga/model/Manga.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ fun Manga.toSManga(): SManga = SManga.create().also {
it.description = description
it.genre = genre.orEmpty().joinToString()
it.status = status.toInt()
it.webUrls = webUrls.orEmpty().joinToString(", ")
it.thumbnail_url = thumbnailUrl
it.initialized = initialized
}
Expand All @@ -59,6 +60,11 @@ fun Manga.copyFrom(other: SManga): Manga {
} else {
genre
}
val webUrls = if (other.webUrls != null) {
other.getWebUrls()
} else {
webUrls
}
val thumbnailUrl = other.thumbnail_url ?: thumbnailUrl
return this.copy(
author = author,
Expand All @@ -67,6 +73,7 @@ fun Manga.copyFrom(other: SManga): Manga {
genre = genres,
thumbnailUrl = thumbnailUrl,
status = other.status.toLong(),
webUrls = webUrls,
updateStrategy = other.update_strategy,
initialized = other.initialized && initialized,
)
Expand All @@ -81,6 +88,7 @@ fun SManga.toDomainManga(sourceId: Long): Manga {
description = description,
genre = getGenres(),
status = status.toLong(),
webUrls = getWebUrls(),
thumbnailUrl = thumbnail_url,
updateStrategy = update_strategy,
initialized = initialized,
Expand Down Expand Up @@ -111,7 +119,16 @@ fun getComicInfo(
ComicInfo.Number(it.toString())
}
},
web = ComicInfo.Web(urls.joinToString(" ")),
web = if (!manga.webUrls.isNullOrEmpty()) {
ComicInfo.Web(
manga.webUrls!!
.plus(urls)
.distinct()
.joinToString(" ")
)
} else {
ComicInfo.Web(urls.joinToString(" "))
},
summary = manga.description?.let { ComicInfo.Summary(it) },
writer = manga.author?.let { ComicInfo.Writer(it) },
penciller = manga.artist?.let { ComicInfo.Penciller(it) },
Expand Down
130 changes: 130 additions & 0 deletions app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
Expand All @@ -17,6 +18,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
Expand All @@ -26,12 +29,16 @@ import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.SuggestionChipDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -51,10 +58,12 @@ import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.presentation.track.components.TrackLogoIcon
import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.TrackerChipElement
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.lang.toLocalDate
import eu.kanade.tachiyomi.util.system.copyToClipboard
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import java.time.format.DateTimeFormatter

Expand All @@ -64,6 +73,7 @@ private const val UnsetStatusTextAlpha = 0.5F
fun TrackInfoDialogHome(
trackItems: List<TrackItem>,
dateFormat: DateTimeFormatter,
webUrlProvider: () -> List<String>?,
onStatusClick: (TrackItem) -> Unit,
onChapterClick: (TrackItem) -> Unit,
onScoreClick: (TrackItem) -> Unit,
Expand All @@ -72,6 +82,9 @@ fun TrackInfoDialogHome(
onNewSearch: (TrackItem) -> Unit,
onOpenInBrowser: (TrackItem) -> Unit,
onRemoved: (TrackItem) -> Unit,
onNewIdSearch: (TrackerChipElement) -> Unit,
onNewChipSearch: (TrackerChipElement) -> Unit,
onOpenChipElementInBrowser: (TrackerChipElement) -> Unit,
) {
Column(
modifier = Modifier
Expand All @@ -82,6 +95,13 @@ fun TrackInfoDialogHome(
.windowInsetsPadding(WindowInsets.systemBars),
verticalArrangement = Arrangement.spacedBy(24.dp),
) {
TrackerRow(
trackItems = trackItems,
webUrlProvider = webUrlProvider,
onNewIdSearch = onNewIdSearch,
onNewChipSearch = onNewChipSearch,
onOpenChipElementInBrowser = onOpenChipElementInBrowser,
)
trackItems.forEach { item ->
if (item.track != null) {
val supportsScoring = item.tracker.getScoreList().isNotEmpty()
Expand Down Expand Up @@ -127,6 +147,84 @@ fun TrackInfoDialogHome(
}
}

@Composable
private fun TrackerRow(
trackItems: List<TrackItem>,
webUrlProvider: () -> List<String>?,
onNewIdSearch: (TrackerChipElement) -> Unit,
onNewChipSearch: (TrackerChipElement) -> Unit,
onOpenChipElementInBrowser: (TrackerChipElement) -> Unit,
) {
val trackerChipElements = webUrlProvider()
?.asSequence()
?.map { TrackerChipElement(it, trackItems) }
?.filter { it.trackItem?.track?.remoteId != it.remoteId || it.trackItem?.track == null }
?.filter { it.serviceId != null }
?.sortedBy { it.serviceId }
?.sortedWith(compareBy(nullsLast()) { it.trackItem?.tracker?.id })
?.toList()

if (!trackerChipElements.isNullOrEmpty()) {
Box(
modifier = Modifier
.padding(top = 8.dp)
.padding(end = 12.dp)
.animateContentSize(),
) {
val context = LocalContext.current
var showMenu by remember { mutableStateOf(false) }
var selectedChipElement: TrackerChipElement? by remember { mutableStateOf(null) }
DropdownMenu(
expanded = showMenu,
onDismissRequest = { showMenu = false },
) {
if (selectedChipElement?.trackItem?.tracker != null) {
DropdownMenuItem(
text = { Text(text = stringResource(MR.strings.action_open_in_mihon)) },
onClick = {
if (selectedChipElement!!.remoteId != null) {
onNewIdSearch(selectedChipElement!!)
} else if (selectedChipElement!!.searchQuery != null) {
onNewChipSearch(selectedChipElement!!)
}
showMenu = false
},
)
}
DropdownMenuItem(
text = { Text(text = stringResource(MR.strings.action_copy_to_clipboard)) },
onClick = {
context.copyToClipboard(selectedChipElement?.url!!, selectedChipElement?.url!!)
showMenu = false
},
)
DropdownMenuItem(
text = { Text(text = stringResource(MR.strings.action_open_in_browser)) },
onClick = {
onOpenChipElementInBrowser(selectedChipElement!!)
showMenu = false
},
)
}
LazyRow(
contentPadding = PaddingValues(horizontal = MaterialTheme.padding.extraSmall),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
) {
items(items = trackerChipElements) { chipElement ->
TrackerChip(
trackerChipElement = chipElement,
modifier = Modifier,
onClick = {
selectedChipElement = chipElement
showMenu = true
},
)
}
}
}
}
}

@Composable
private fun TrackInfoItem(
title: String,
Expand Down Expand Up @@ -318,6 +416,38 @@ private fun TrackInfoItemMenu(
}
}

@Composable
fun TrackerChip(
trackerChipElement: TrackerChipElement,
modifier: Modifier = Modifier,
onClick: () -> Unit,
) {
CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) {
SuggestionChip(
modifier = modifier,
onClick = onClick,
colors = SuggestionChipDefaults.suggestionChipColors().copy(),
icon = {
trackerChipElement.icon?.let { icon ->
Icon(
imageVector = icon,
contentDescription = null,
)
}
},
label = {
trackerChipElement.trackerName?.let { name ->
Text(
text = name,
style = MaterialTheme.typography.bodySmall,
maxLines = 1,
)
}
},
)
}
}

@PreviewLightDark
@Composable
private fun TrackInfoDialogHomePreviews(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ internal class TrackInfoDialogHomePreviewProvider :
trackItemWithTrack,
),
dateFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM),
webUrlProvider = { listOf(aTrack.remoteUrl) },
onStatusClick = {},
onChapterClick = {},
onScoreClick = {},
Expand All @@ -56,13 +57,17 @@ internal class TrackInfoDialogHomePreviewProvider :
onNewSearch = {},
onOpenInBrowser = {},
onRemoved = {},
onNewIdSearch = {},
onNewChipSearch = {},
onOpenChipElementInBrowser = {},
)
}

private val noTrackers = @Composable {
TrackInfoDialogHome(
trackItems = listOf(),
dateFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM),
webUrlProvider = { listOf(aTrack.remoteUrl) },
onStatusClick = {},
onChapterClick = {},
onScoreClick = {},
Expand All @@ -71,6 +76,9 @@ internal class TrackInfoDialogHomePreviewProvider :
onNewSearch = {},
onOpenInBrowser = {},
onRemoved = {},
onNewIdSearch = {},
onNewChipSearch = {},
onOpenChipElementInBrowser = {},
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ private fun Manga.toBackupManga() =
description = this.description,
genre = this.genre.orEmpty(),
status = this.status.toInt(),
webUrls = this.webUrls.orEmpty(),
thumbnailUrl = this.thumbnailUrl,
favorite = this.favorite,
source = this.source,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ data class BackupManga(
@ProtoNumber(107) var favoriteModifiedAt: Long? = null,
@ProtoNumber(108) var excludedScanlators: List<String> = emptyList(),
@ProtoNumber(109) var version: Long = 0,
@ProtoNumber(110) var webUrls: List<String>? = emptyList(),

) {
fun getMangaImpl(): Manga {
return Manga.create().copy(
Expand All @@ -53,6 +55,7 @@ data class BackupManga(
description = [email protected],
genre = [email protected],
status = [email protected](),
webUrls = [email protected],
thumbnailUrl = [email protected],
favorite = [email protected],
source = [email protected],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class MangaRestorer(
artist = newer.artist,
description = newer.description,
genre = newer.genre,
webUrls = newer.webUrls,
thumbnailUrl = newer.thumbnailUrl,
status = newer.status,
initialized = this.initialized || newer.initialized,
Expand All @@ -115,6 +116,7 @@ class MangaRestorer(
genre = manga.genre?.joinToString(separator = ", "),
title = manga.title,
status = manga.status,
webUrls = manga.webUrls?.joinToString(separator = ", "),
thumbnailUrl = manga.thumbnailUrl,
favorite = manga.favorite,
lastUpdate = manga.lastUpdate,
Expand Down Expand Up @@ -249,6 +251,7 @@ class MangaRestorer(
genre = manga.genre,
title = manga.title,
status = manga.status,
webUrls = manga.webUrls,
thumbnailUrl = manga.thumbnailUrl,
favorite = manga.favorite,
lastUpdate = manga.lastUpdate,
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ interface Tracker {

suspend fun login(username: String, password: String)

suspend fun searchId(id: Long): List<TrackSearch>

@CallSuper
fun logout()

Expand Down
Loading