mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-09 19:55:11 +01:00
Added tracking sheet to manga details
Using the compact card view dev tachi is for now, maybe forever Also finally fixed the anilist bug Co-Authored-By: arkon <arkon@users.noreply.github.com>
This commit is contained in:
parent
8134d4c2fa
commit
29134f6bb0
@ -1,18 +1,13 @@
|
||||
package eu.kanade.tachiyomi.data.track.anilist
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
data class ALManga(
|
||||
val media_id: Int,
|
||||
@ -45,12 +40,11 @@ data class ALManga(
|
||||
}
|
||||
|
||||
data class ALUserManga(
|
||||
val library_id: Long,
|
||||
val list_status: String,
|
||||
val score_raw: Int,
|
||||
val chapters_read: Int,
|
||||
val manga: ALManga,
|
||||
val context: Context = Injekt.get<PreferencesHelper>().context
|
||||
val library_id: Long,
|
||||
val list_status: String,
|
||||
val score_raw: Int,
|
||||
val chapters_read: Int,
|
||||
val manga: ALManga
|
||||
) {
|
||||
|
||||
fun toTrack() = Track.create(TrackManager.ANILIST).apply {
|
||||
@ -62,16 +56,14 @@ data class ALUserManga(
|
||||
total_chapters = manga.total_chapters
|
||||
}
|
||||
|
||||
fun toTrackStatus() = with(context) {
|
||||
when (list_status) {
|
||||
getString(R.string.reading) -> Anilist.READING
|
||||
getString(R.string.completed) -> Anilist.COMPLETED
|
||||
getString(R.string.paused) -> Anilist.PAUSED
|
||||
getString(R.string.dropped) -> Anilist.DROPPED
|
||||
getString(R.string.plan_to_read) -> Anilist.PLANNING
|
||||
getString(R.string.repeating)-> Anilist.REPEATING
|
||||
else -> throw NotImplementedError("Unknown status")
|
||||
}
|
||||
fun toTrackStatus() = when (list_status) {
|
||||
"CURRENT" -> Anilist.READING
|
||||
"COMPLETED" -> Anilist.COMPLETED
|
||||
"PAUSED" -> Anilist.PAUSED
|
||||
"DROPPED" -> Anilist.DROPPED
|
||||
"PLANNING" -> Anilist.PLANNING
|
||||
"REPEATING" -> Anilist.REPEATING
|
||||
else -> throw NotImplementedError("Unknown status")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ import eu.kanade.tachiyomi.data.download.DownloadService
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
@ -78,6 +79,7 @@ import eu.kanade.tachiyomi.ui.manga.chapter.ChapterMatHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.DownloadCustomChaptersDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.info.EditMangaDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
@ -143,6 +145,7 @@ class MangaDetailsController : BaseController,
|
||||
private var snack: Snackbar? = null
|
||||
val fromCatalogue = args.getBoolean(FROM_CATALOGUE_EXTRA, false)
|
||||
var coverDrawable:Drawable? = null
|
||||
var trackingBottomSheet: TrackingBottomSheet? = null
|
||||
/**
|
||||
* Adapter containing a list of chapters.
|
||||
*/
|
||||
@ -444,6 +447,8 @@ class MangaDetailsController : BaseController,
|
||||
override fun onDestroyView(view: View) {
|
||||
snack?.dismiss()
|
||||
presenter.onDestroy()
|
||||
adapter = null
|
||||
trackingBottomSheet = null
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
|
||||
@ -869,6 +874,36 @@ class MangaDetailsController : BaseController,
|
||||
return super.handleBack()
|
||||
}
|
||||
|
||||
override fun showTrackingSheet() {
|
||||
trackingBottomSheet = TrackingBottomSheet(this)
|
||||
trackingBottomSheet?.show()
|
||||
}
|
||||
|
||||
fun refreshTracking(trackings: List<TrackItem>) {
|
||||
trackingBottomSheet?.onNextTrackings(trackings)
|
||||
}
|
||||
|
||||
fun onTrackSearchResults(results: List<TrackSearch>) {
|
||||
trackingBottomSheet?.onSearchResults(results)
|
||||
}
|
||||
|
||||
fun refreshTracker() {
|
||||
(recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder)
|
||||
?.updateTracking()
|
||||
}
|
||||
|
||||
fun trackRefreshDone() {
|
||||
trackingBottomSheet?.onRefreshDone()
|
||||
}
|
||||
|
||||
fun trackRefreshError(error: Exception) {
|
||||
trackingBottomSheet?.onRefreshError(error)
|
||||
}
|
||||
|
||||
fun trackSearchError(error: Exception) {
|
||||
trackingBottomSheet?.onSearchResultsError(error)
|
||||
}
|
||||
|
||||
override fun zoomImageFromThumb(thumbView: View) {
|
||||
// If there's an animation in progress, cancel it immediately and proceed with this one.
|
||||
currentAnimator?.cancel()
|
||||
|
@ -20,11 +20,13 @@ import eu.kanade.tachiyomi.data.library.LibraryServiceListener
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
@ -62,6 +64,7 @@ class MangaDetailsPresenter(private val controller: MangaDetailsController,
|
||||
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLogged } }
|
||||
var tracks = emptyList<Track>()
|
||||
|
||||
var trackList: List<TrackItem> = emptyList()
|
||||
|
||||
var chapters:List<ChapterItem> = emptyList()
|
||||
private set
|
||||
@ -73,6 +76,7 @@ class MangaDetailsPresenter(private val controller: MangaDetailsController,
|
||||
headerItem.isLocked = isLockedFromSearch
|
||||
downloadManager.addListener(this)
|
||||
LibraryUpdateService.setListener(this)
|
||||
tracks = db.getTracks(manga).executeAsBlocking()
|
||||
if (!manga.initialized) {
|
||||
isLoading = true
|
||||
controller.setRefresh(true)
|
||||
@ -81,9 +85,9 @@ class MangaDetailsPresenter(private val controller: MangaDetailsController,
|
||||
}
|
||||
else {
|
||||
updateChapters()
|
||||
tracks = db.getTracks(manga).executeAsBlocking()
|
||||
controller.updateChapters(this.chapters)
|
||||
}
|
||||
fetchTrackings()
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
@ -161,7 +165,7 @@ class MangaDetailsPresenter(private val controller: MangaDetailsController,
|
||||
}
|
||||
/**
|
||||
* Sets the active display mode.
|
||||
* @param mode the mode to set.
|
||||
* @param hide set title to hidden
|
||||
*/
|
||||
fun hideTitle(hide: Boolean) {
|
||||
manga.displayMode = if (hide) Manga.DISPLAY_NUMBER else Manga.DISPLAY_NAME
|
||||
@ -658,7 +662,124 @@ class MangaDetailsPresenter(private val controller: MangaDetailsController,
|
||||
return false
|
||||
}
|
||||
|
||||
fun isTracked(): Boolean {
|
||||
return loggedServices.any { service -> tracks.any { it.sync_id == service.id } }
|
||||
fun isTracked(): Boolean = loggedServices.any { service -> tracks.any { it.sync_id == service.id } }
|
||||
|
||||
fun hasTrackers(): Boolean = loggedServices.isNotEmpty()
|
||||
|
||||
|
||||
// Tracking
|
||||
|
||||
private fun fetchTrackings() {
|
||||
launch {
|
||||
trackList = loggedServices.map { service ->
|
||||
TrackItem(tracks.find { it.sync_id == service.id }, service)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun refreshTracking() {
|
||||
tracks = withContext(Dispatchers.IO) { db.getTracks(manga).executeAsBlocking() }
|
||||
trackList = loggedServices.map { service ->
|
||||
TrackItem(tracks.find { it.sync_id == service.id }, service)
|
||||
}
|
||||
withContext(Dispatchers.Main) { controller.refreshTracking(trackList) }
|
||||
}
|
||||
|
||||
fun refreshTrackers() {
|
||||
launch {
|
||||
val list = trackList.filter { it.track != null }.map { item ->
|
||||
withContext(Dispatchers.IO) {
|
||||
val trackItem = try {
|
||||
item.service.refresh(item.track!!).toBlocking().single()
|
||||
} catch (e: Exception) {
|
||||
trackError(e)
|
||||
null
|
||||
}
|
||||
if (trackItem != null) {
|
||||
db.insertTrack(trackItem).executeAsBlocking()
|
||||
trackItem
|
||||
}
|
||||
else
|
||||
item.track
|
||||
}
|
||||
}
|
||||
refreshTracking()
|
||||
}
|
||||
}
|
||||
|
||||
fun trackSearch(query: String, service: TrackService) {
|
||||
launch(Dispatchers.IO) {
|
||||
val results = try {service.search(query).toBlocking().single() }
|
||||
catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) { controller.trackSearchError(e) }
|
||||
null }
|
||||
if (!results.isNullOrEmpty()) {
|
||||
withContext(Dispatchers.Main) { controller.onTrackSearchResults(results) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun registerTracking(item: Track?, service: TrackService) {
|
||||
if (item != null) {
|
||||
item.manga_id = manga.id!!
|
||||
|
||||
launch {
|
||||
val binding = try { service.bind(item).toBlocking().single() }
|
||||
catch (e: Exception) {
|
||||
trackError(e)
|
||||
null
|
||||
}
|
||||
withContext(Dispatchers.IO) {
|
||||
if (binding != null) db.insertTrack(binding).executeAsBlocking() }
|
||||
refreshTracking()
|
||||
}
|
||||
} else {
|
||||
launch {
|
||||
withContext(Dispatchers.IO) { db.deleteTrackForManga(manga, service)
|
||||
.executeAsBlocking() }
|
||||
refreshTracking()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRemote(track: Track, service: TrackService) {
|
||||
launch {
|
||||
val binding = try { service.update(track).toBlocking().single() }
|
||||
catch (e: Exception) {
|
||||
trackError(e)
|
||||
null
|
||||
}
|
||||
if (binding != null) {
|
||||
withContext(Dispatchers.IO) { db.insertTrack(binding).executeAsBlocking() }
|
||||
refreshTracking()
|
||||
}
|
||||
else trackRefreshDone()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun trackRefreshDone() {
|
||||
async(Dispatchers.Main) { controller.trackRefreshDone() }
|
||||
}
|
||||
|
||||
private suspend fun trackError(error: Exception) {
|
||||
async(Dispatchers.Main) { controller.trackRefreshError(error) }
|
||||
}
|
||||
|
||||
fun setStatus(item: TrackItem, index: Int) {
|
||||
val track = item.track!!
|
||||
track.status = item.service.getStatusList()[index]
|
||||
updateRemote(track, item.service)
|
||||
}
|
||||
|
||||
fun setScore(item: TrackItem, index: Int) {
|
||||
val track = item.track!!
|
||||
track.score = item.service.indexToScore(index)
|
||||
updateRemote(track, item.service)
|
||||
}
|
||||
|
||||
fun setLastChapterRead(item: TrackItem, chapterNumber: Int) {
|
||||
val track = item.track!!
|
||||
track.last_chapter_read = chapterNumber
|
||||
updateRemote(track, item.service)
|
||||
}
|
||||
}
|
@ -54,7 +54,7 @@ class MangaHeaderHolder(
|
||||
filters_text.setOnClickListener { adapter.coverListener?.showChapterFilter() }
|
||||
chapters_title.setOnClickListener { adapter.coverListener?.showChapterFilter() }
|
||||
webview_button.setOnClickListener { adapter.coverListener?.openInWebView() }
|
||||
share_button.setOnClickListener { adapter.coverListener?.prepareToShareManga() }
|
||||
share_button.setOnClickListener { adapter.coverListener?.prepareToShareManga() }
|
||||
favorite_button.setOnClickListener {
|
||||
adapter.coverListener?.favoriteManga(false)
|
||||
}
|
||||
@ -71,6 +71,7 @@ class MangaHeaderHolder(
|
||||
true
|
||||
}
|
||||
manga_cover.setOnClickListener { adapter.coverListener?.zoomImageFromThumb(cover_card) }
|
||||
track_button.setOnClickListener { adapter.coverListener?.showTrackingSheet() }
|
||||
if (startExpanded)
|
||||
expandDesc()
|
||||
}
|
||||
@ -144,6 +145,7 @@ class MangaHeaderHolder(
|
||||
val tracked = presenter.isTracked() && !item.isLocked
|
||||
|
||||
with(track_button) {
|
||||
visibleIf(presenter.hasTrackers())
|
||||
text = itemView.context.getString(if (tracked) R.string.action_filter_tracked
|
||||
else R.string.tracking)
|
||||
|
||||
@ -232,6 +234,19 @@ class MangaHeaderHolder(
|
||||
true_backdrop.setBackgroundColor(color)
|
||||
}
|
||||
|
||||
fun updateTracking() {
|
||||
val presenter = adapter.coverListener?.mangaPresenter() ?: return
|
||||
val tracked = presenter.isTracked()
|
||||
with(track_button) {
|
||||
text = itemView.context.getString(if (tracked) R.string.action_filter_tracked
|
||||
else R.string.tracking)
|
||||
|
||||
icon = ContextCompat.getDrawable(itemView.context, if (tracked) R.drawable
|
||||
.ic_check_white_24dp else R.drawable.ic_sync_black_24dp)
|
||||
checked(tracked)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLongClick(view: View?): Boolean {
|
||||
super.onLongClick(view)
|
||||
return false
|
||||
|
@ -0,0 +1,185 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.ui.manga.track.SetTrackChaptersDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.track.SetTrackScoreDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.track.SetTrackStatusDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackAdapter
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackSearchDialog
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
||||
import eu.kanade.tachiyomi.util.view.setEdgeToEdge
|
||||
import kotlinx.android.synthetic.main.tracking_bottom_sheet.*
|
||||
import timber.log.Timber
|
||||
|
||||
class TrackingBottomSheet(private val controller: MangaDetailsController) : BottomSheetDialog
|
||||
(controller.activity!!, R.style.BottomSheetDialogTheme),
|
||||
TrackAdapter.OnClickListener,
|
||||
SetTrackStatusDialog.Listener,
|
||||
SetTrackChaptersDialog.Listener,
|
||||
SetTrackScoreDialog.Listener {
|
||||
|
||||
val activity = controller.activity!!
|
||||
|
||||
private var sheetBehavior: BottomSheetBehavior<*>
|
||||
|
||||
val presenter = controller.presenter
|
||||
|
||||
private var adapter: TrackAdapter? = null
|
||||
|
||||
init {
|
||||
// Use activity theme for this layout
|
||||
val view = activity.layoutInflater.inflate(R.layout.tracking_bottom_sheet, null)
|
||||
setContentView(view)
|
||||
|
||||
sheetBehavior = BottomSheetBehavior.from(view.parent as ViewGroup)
|
||||
setEdgeToEdge(activity, display_bottom_sheet, view, false)
|
||||
val height = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
activity.window.decorView.rootWindowInsets.systemWindowInsetBottom
|
||||
} else 0
|
||||
sheetBehavior.peekHeight = 380.dpToPx + height
|
||||
|
||||
sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onSlide(bottomSheet: View, progress: Float) { }
|
||||
|
||||
override fun onStateChanged(p0: View, state: Int) {
|
||||
if (state == BottomSheetBehavior.STATE_EXPANDED) {
|
||||
sheetBehavior.skipCollapsed = true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
sheetBehavior.skipCollapsed = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the sheet is created. It initializes the listeners and values of the preferences.
|
||||
*/
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
adapter = TrackAdapter(this)
|
||||
track_recycler.layoutManager = LinearLayoutManager(context)
|
||||
track_recycler.adapter = adapter
|
||||
track_recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
|
||||
|
||||
adapter?.items = presenter.trackList
|
||||
}
|
||||
|
||||
fun onNextTrackings(trackings: List<TrackItem>) {
|
||||
onRefreshDone()
|
||||
adapter?.items = trackings
|
||||
controller.refreshTracker()
|
||||
}
|
||||
|
||||
fun onSearchResults(results: List<TrackSearch>) {
|
||||
getSearchDialog()?.onSearchResults(results)
|
||||
}
|
||||
|
||||
fun onSearchResultsError(error: Throwable) {
|
||||
Timber.e(error)
|
||||
getSearchDialog()?.onSearchResultsError()
|
||||
}
|
||||
|
||||
private fun getSearchDialog(): TrackSearchDialog? {
|
||||
return controller.router.getControllerWithTag(TAG_SEARCH_CONTROLLER) as? TrackSearchDialog
|
||||
}
|
||||
|
||||
fun onRefreshDone() {
|
||||
for (i in adapter!!.items.indices) {
|
||||
(track_recycler.findViewHolderForAdapterPosition(i) as? TrackHolder)?.setProgress(false)
|
||||
}
|
||||
}
|
||||
|
||||
fun onRefreshError(error: Throwable) {
|
||||
for (i in adapter!!.items.indices) {
|
||||
(track_recycler.findViewHolderForAdapterPosition(i) as? TrackHolder)?.setProgress(false)
|
||||
}
|
||||
activity.toast(error.message)
|
||||
}
|
||||
|
||||
override fun onLogoClick(position: Int) {
|
||||
val track = adapter?.getItem(position)?.track ?: return
|
||||
|
||||
if (track.tracking_url.isBlank()) {
|
||||
activity.toast(R.string.url_not_set)
|
||||
} else {
|
||||
activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(track.tracking_url)))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSetClick(position: Int) {
|
||||
val item = adapter?.getItem(position) ?: return
|
||||
TrackSearchDialog(this, item.service, item.track != null).showDialog(
|
||||
controller.router, TAG_SEARCH_CONTROLLER)
|
||||
}
|
||||
|
||||
override fun onStatusClick(position: Int) {
|
||||
val item = adapter?.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
|
||||
SetTrackStatusDialog(this, item).showDialog(controller.router)
|
||||
}
|
||||
|
||||
override fun onChaptersClick(position: Int) {
|
||||
val item = adapter?.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
|
||||
SetTrackChaptersDialog(this, item).showDialog(controller.router)
|
||||
}
|
||||
|
||||
override fun onScoreClick(position: Int) {
|
||||
val item = adapter?.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
|
||||
SetTrackScoreDialog(this, item).showDialog(controller.router)
|
||||
}
|
||||
|
||||
override fun setStatus(item: TrackItem, selection: Int) {
|
||||
presenter.setStatus(item, selection)
|
||||
refreshItem(item)
|
||||
}
|
||||
|
||||
private fun refreshItem(item: TrackItem) {
|
||||
refreshTrack(item.service)
|
||||
}
|
||||
|
||||
fun refreshTrack(item: TrackService?) {
|
||||
val index = adapter?.indexOf(item) ?: -1
|
||||
if (index > -1 ){
|
||||
(track_recycler.findViewHolderForAdapterPosition(index) as? TrackHolder)
|
||||
?.setProgress(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setScore(item: TrackItem, score: Int) {
|
||||
presenter.setScore(item, score)
|
||||
refreshItem(item)
|
||||
}
|
||||
|
||||
override fun setChaptersRead(item: TrackItem, chaptersRead: Int) {
|
||||
presenter.setLastChapterRead(item, chaptersRead)
|
||||
refreshItem(item)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TAG_SEARCH_CONTROLLER = "track_search_controller"
|
||||
}
|
||||
}
|
@ -71,5 +71,6 @@ class ChaptersAdapter(
|
||||
fun favoriteManga(longPress: Boolean)
|
||||
fun copyToClipboard(content: String, label: Int)
|
||||
fun zoomImageFromThumb(thumbView: View)
|
||||
fun showTrackingSheet()
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import android.widget.NumberPicker
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.afollestad.materialdialogs.customview.getCustomView
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
@ -15,14 +14,15 @@ import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class SetTrackChaptersDialog<T> : DialogController
|
||||
where T : Controller, T : SetTrackChaptersDialog.Listener {
|
||||
where T : SetTrackChaptersDialog.Listener {
|
||||
|
||||
private val item: TrackItem
|
||||
private lateinit var listener: Listener
|
||||
|
||||
constructor(target: T, item: TrackItem) : super(Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}) {
|
||||
targetController = target
|
||||
listener = target
|
||||
this.item = item
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ class SetTrackChaptersDialog<T> : DialogController
|
||||
// Remove focus to update selected number
|
||||
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
||||
np.clearFocus()
|
||||
(targetController as? Listener)?.setChaptersRead(item, np.value)
|
||||
listener.setChaptersRead(item, np.value)
|
||||
}
|
||||
|
||||
val view = dialog.getCustomView()
|
||||
|
@ -15,14 +15,15 @@ import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class SetTrackScoreDialog<T> : DialogController
|
||||
where T : Controller, T : SetTrackScoreDialog.Listener {
|
||||
where T : SetTrackScoreDialog.Listener {
|
||||
|
||||
private val item: TrackItem
|
||||
private lateinit var listener: Listener
|
||||
|
||||
constructor(target: T, item: TrackItem) : super(Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}) {
|
||||
targetController = target
|
||||
listener = target
|
||||
this.item = item
|
||||
}
|
||||
|
||||
@ -46,8 +47,7 @@ class SetTrackScoreDialog<T> : DialogController
|
||||
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
||||
np.clearFocus()
|
||||
|
||||
(targetController as? Listener)?.setScore(item, np.value)
|
||||
|
||||
listener.setScore(item, np.value)
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,7 +4,6 @@ import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItemsSingleChoice
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
@ -13,14 +12,16 @@ import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class SetTrackStatusDialog<T> : DialogController
|
||||
where T : Controller, T : SetTrackStatusDialog.Listener {
|
||||
where T : SetTrackStatusDialog.Listener {
|
||||
|
||||
private val item: TrackItem
|
||||
private lateinit var listener: Listener
|
||||
|
||||
constructor(target: T, item: TrackItem) : super(Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}) {
|
||||
targetController = target
|
||||
listener = target
|
||||
// targetController = target
|
||||
this.item = item
|
||||
}
|
||||
|
||||
@ -43,7 +44,7 @@ class SetTrackStatusDialog<T> : DialogController
|
||||
.listItemsSingleChoice(items = statusString, initialSelection = selectedIndex,
|
||||
waitForPositiveButton = false)
|
||||
{ dialog, position, _ ->
|
||||
(targetController as? Listener)?.setStatus(item, position)
|
||||
listener.setStatus(item, position)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.track
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.util.view.inflate
|
||||
|
||||
class TrackAdapter(controller: TrackController) : RecyclerView.Adapter<TrackHolder>() {
|
||||
class TrackAdapter(controller: OnClickListener) : RecyclerView.Adapter<TrackHolder>() {
|
||||
|
||||
var items = emptyList<TrackItem>()
|
||||
set(value) {
|
||||
@ -34,9 +35,13 @@ class TrackAdapter(controller: TrackController) : RecyclerView.Adapter<TrackHold
|
||||
holder.bind(items[position])
|
||||
}
|
||||
|
||||
fun indexOf(item: TrackService?):Int {
|
||||
return items.indexOfFirst { item?.id == it.service.id }
|
||||
}
|
||||
|
||||
interface OnClickListener {
|
||||
fun onLogoClick(position: Int)
|
||||
fun onTitleClick(position: Int)
|
||||
fun onSetClick(position: Int)
|
||||
fun onStatusClick(position: Int)
|
||||
fun onChaptersClick(position: Int)
|
||||
fun onScoreClick(position: Int)
|
||||
|
@ -119,7 +119,7 @@ class TrackController : NucleusController<TrackPresenter>(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTitleClick(position: Int) {
|
||||
override fun onSetClick(position: Int) {
|
||||
val item = adapter?.getItem(position) ?: return
|
||||
TrackSearchDialog(this, item.service, item.track != null).showDialog(router,
|
||||
TAG_SEARCH_CONTROLLER)
|
||||
|
@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.manga.track
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.View
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseViewHolder
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import kotlinx.android.synthetic.main.track_item.*
|
||||
|
||||
class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
||||
@ -11,32 +11,28 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
||||
init {
|
||||
val listener = adapter.rowClickListener
|
||||
logo_container.setOnClickListener { listener.onLogoClick(adapterPosition) }
|
||||
title_container.setOnClickListener { listener.onTitleClick(adapterPosition) }
|
||||
track_set.setOnClickListener { listener.onSetClick(adapterPosition) }
|
||||
status_container.setOnClickListener { listener.onStatusClick(adapterPosition) }
|
||||
chapters_container.setOnClickListener { listener.onChaptersClick(adapterPosition) }
|
||||
score_container.setOnClickListener { listener.onScoreClick(adapterPosition) }
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Suppress("DEPRECATION")
|
||||
fun bind(item: TrackItem) {
|
||||
val track = item.track
|
||||
track_logo.setImageResource(item.service.getLogo())
|
||||
logo_container.setBackgroundColor(item.service.getLogoColor())
|
||||
track_group.visibleIf(track != null)
|
||||
if (track != null) {
|
||||
track_title.setTextAppearance(itemView.context, R.style.TextAppearance_Regular_Body1_Secondary)
|
||||
track_title.isAllCaps = false
|
||||
track_title.text = track.title
|
||||
track_chapters.text = "${track.last_chapter_read}/" +
|
||||
if (track.total_chapters > 0) track.total_chapters else "-"
|
||||
track_status.text = item.service.getStatus(track.status)
|
||||
track_score.text = if (track.score == 0f) "-" else item.service.displayScore(track)
|
||||
} else {
|
||||
track_title.setTextAppearance(itemView.context, R.style.TextAppearance_Medium_Button)
|
||||
track_title.setText(R.string.action_edit)
|
||||
track_chapters.text = ""
|
||||
track_score.text = ""
|
||||
track_status.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
fun setProgress(enabled: Boolean) {
|
||||
progress.visibleIf(enabled)
|
||||
track_logo.visibleIf(!enabled)
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,10 @@ import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import kotlinx.android.synthetic.main.track_controller.*
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsPresenter
|
||||
import eu.kanade.tachiyomi.ui.manga.TrackingBottomSheet
|
||||
import eu.kanade.tachiyomi.util.lang.plusAssign
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.progress
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.track_search
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.track_search_list
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.*
|
||||
import rx.Subscription
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.subscriptions.CompositeSubscription
|
||||
@ -41,10 +40,14 @@ class TrackSearchDialog : DialogController {
|
||||
|
||||
private var searchTextSubscription: Subscription? = null
|
||||
|
||||
private val trackController
|
||||
get() = targetController as TrackController
|
||||
private lateinit var bottomSheet: TrackingBottomSheet
|
||||
//private val trackController
|
||||
// get() = targetController as TrackController
|
||||
|
||||
|
||||
|
||||
private var wasPreviouslyTracked:Boolean = false
|
||||
private lateinit var presenter:MangaDetailsPresenter
|
||||
|
||||
constructor(target: TrackController, service: TrackService, wasTracked:Boolean) : super(Bundle()
|
||||
.apply {
|
||||
@ -55,6 +58,16 @@ class TrackSearchDialog : DialogController {
|
||||
this.service = service
|
||||
}
|
||||
|
||||
constructor(target: TrackingBottomSheet, service: TrackService, wasTracked:Boolean) : super(Bundle()
|
||||
.apply {
|
||||
putInt(KEY_SERVICE, service.id)
|
||||
}) {
|
||||
wasPreviouslyTracked = wasTracked
|
||||
bottomSheet = target
|
||||
presenter = target.presenter
|
||||
this.service = service
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
constructor(bundle: Bundle) : super(bundle) {
|
||||
service = Injekt.get<TrackManager>().getService(bundle.getInt(KEY_SERVICE))!!
|
||||
@ -97,7 +110,7 @@ class TrackSearchDialog : DialogController {
|
||||
|
||||
// Do an initial search based on the manga's title
|
||||
if (savedState == null) {
|
||||
val title = trackController.presenter.manga.originalTitle()
|
||||
val title = presenter.manga.originalTitle()
|
||||
view.track_search.append(title)
|
||||
search(title)
|
||||
}
|
||||
@ -129,7 +142,7 @@ class TrackSearchDialog : DialogController {
|
||||
val view = dialogView ?: return
|
||||
view.progress.visibility = View.VISIBLE
|
||||
view.track_search_list.visibility = View.INVISIBLE
|
||||
trackController.presenter.search(query, service)
|
||||
presenter.trackSearch(query, service)
|
||||
}
|
||||
|
||||
fun onSearchResults(results: List<TrackSearch>) {
|
||||
@ -153,8 +166,10 @@ class TrackSearchDialog : DialogController {
|
||||
}
|
||||
|
||||
private fun onPositiveButtonClick() {
|
||||
trackController.swipe_refresh.isRefreshing = true
|
||||
trackController.presenter.registerTracking(selectedItem, service)
|
||||
// trackController.swipe_refresh.isRefreshing = true
|
||||
bottomSheet.refreshTrack(service)
|
||||
presenter.registerTracking(selectedItem,
|
||||
service)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
@ -169,7 +169,7 @@ inline val View.marginLeft: Int
|
||||
|
||||
object RecyclerWindowInsetsListener : View.OnApplyWindowInsetsListener {
|
||||
override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets {
|
||||
v.setPadding(0,0,0,insets.systemWindowInsetBottom)
|
||||
v.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
|
||||
//v.updatePaddingRelative(bottom = v.paddingBottom + insets.systemWindowInsetBottom)
|
||||
return insets
|
||||
}
|
||||
|
@ -1,22 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/track"
|
||||
style="@style/Theme.Widget.CardView.Item"
|
||||
android:padding="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/colorBackground"
|
||||
android:minHeight="?attr/actionBarSize">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/logo_container"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="0dp"
|
||||
android:foreground="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/status_container"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:clickable="true"
|
||||
tools:background="#2E51A2">
|
||||
|
||||
<ImageView
|
||||
@ -26,48 +33,21 @@
|
||||
android:layout_gravity="center"
|
||||
tools:src="@drawable/tracker_mal" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/title_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectable_list_drawable"
|
||||
android:clickable="true"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/logo_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.Regular.Body1"
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title" />
|
||||
android:layout_gravity="center"
|
||||
android:padding="4dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_title"
|
||||
style="@style/TextAppearance.Medium.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/action_edit" />
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="?android:attr/divider"
|
||||
app:layout_constraintStart_toEndOf="@+id/logo_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title_container" />
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/track_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="chapters_container,status_container,score_container" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/status_container"
|
||||
@ -75,106 +55,114 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectable_list_drawable"
|
||||
android:clickable="true"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/logo_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider1">
|
||||
android:focusable="true"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintStart_toEndOf="@id/logo_container"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/chapters_container"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.Regular.Body1"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/status" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_status"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:gravity="end"
|
||||
tools:text="Reading" />
|
||||
android:layout_marginTop="8dp"
|
||||
tools:text="Currently Reading" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="?android:attr/divider"
|
||||
app:layout_constraintStart_toEndOf="@+id/logo_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/status_container" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/chapters_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constrainedHeight="true"
|
||||
android:background="?attr/selectable_list_drawable"
|
||||
android:clickable="true"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/logo_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider2">
|
||||
android:focusable="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="16dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/status_container"
|
||||
app:layout_constraintEnd_toStartOf="@id/score_container"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.Regular.Body1"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/chapters" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_chapters"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
tools:text="12/24" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="?android:attr/divider"
|
||||
app:layout_constraintStart_toEndOf="@+id/logo_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/chapters_container" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/score_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:background="?attr/selectable_list_drawable"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:clickable="true"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/logo_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider3">
|
||||
android:focusable="true"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/chapters_container"
|
||||
app:layout_constraintEnd_toStartOf="@id/track_set"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.Regular.Body1"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/score" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_score"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
tools:text="10" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/track_set"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/action_edit"
|
||||
android:padding="8dp"
|
||||
android:tint="?android:attr/textColorSecondary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/score_container"
|
||||
app:srcCompat="@drawable/ic_edit_white_24dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
</com.google.android.material.card.MaterialCardView>
|
14
app/src/main/res/layout/tracking_bottom_sheet.xml
Normal file
14
app/src/main/res/layout/tracking_bottom_sheet.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/display_bottom_sheet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/track_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/bg_bottom_sheet_dialog_fragment"
|
||||
tools:listitem="@layout/track_item" />
|
||||
</FrameLayout>
|
@ -149,7 +149,7 @@
|
||||
<item name="layout_behavior">eu.kanade.tachiyomi.widget.FABMoveBehaviour</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Widget.CardView" parent="CardView">
|
||||
<style name="Theme.Widget.CardView" parent="Widget.MaterialComponents.CardView">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:padding">@dimen/material_component_cards_top_and_bottom_padding</item>
|
||||
|
Loading…
Reference in New Issue
Block a user