Added Start/Completed Date for MAL

Co-Authored-By: arkon <4098258+arkon@users.noreply.github.com>
This commit is contained in:
Jays2Kings 2021-03-21 22:28:16 -04:00
parent 05e3437f49
commit 4ccd051cd5
16 changed files with 272 additions and 22 deletions

View File

@ -22,9 +22,9 @@ data class BackupTracking(
@ProtoNumber(8) var score: Float = 0F,
@ProtoNumber(9) var status: Int = 0,
// startedReadingDate is called startReadTime in 1.x
// @ProtoNumber(10) var startedReadingDate: Long = 0,
@ProtoNumber(10) var startedReadingDate: Long = 0,
// finishedReadingDate is called endReadTime in 1.x
// @ProtoNumber(11) var finishedReadingDate: Long = 0,
@ProtoNumber(11) var finishedReadingDate: Long = 0,
) {
fun getTrackingImpl(): TrackImpl {
return TrackImpl().apply {
@ -37,8 +37,8 @@ data class BackupTracking(
total_chapters = this@BackupTracking.totalChapters
score = this@BackupTracking.score
status = this@BackupTracking.status
// started_reading_date = this@BackupTracking.startedReadingDate
// finished_reading_date = this@BackupTracking.finishedReadingDate
started_reading_date = this@BackupTracking.startedReadingDate
finished_reading_date = this@BackupTracking.finishedReadingDate
tracking_url = this@BackupTracking.trackingUrl
}
}
@ -56,8 +56,8 @@ data class BackupTracking(
totalChapters = track.total_chapters,
score = track.score,
status = track.status,
// startedReadingDate = track.started_reading_date,
// finishedReadingDate = track.finished_reading_date,
startedReadingDate = track.started_reading_date,
finishedReadingDate = track.finished_reading_date,
trackingUrl = track.tracking_url
)
}

View File

@ -20,7 +20,7 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
/**
* Version of the database.
*/
const val DATABASE_VERSION = 12
const val DATABASE_VERSION = 13
}
override fun onCreate(db: SupportSQLiteDatabase) = with(db) {
@ -83,6 +83,10 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
if (oldVersion < 12) {
db.execSQL(MangaTable.addDateAddedCol)
}
if (oldVersion < 13) {
db.execSQL(TrackTable.addStartDate)
db.execSQL(TrackTable.addFinishDate)
}
}
override fun onConfigure(db: SupportSQLiteDatabase) {

View File

@ -11,12 +11,14 @@ import com.pushtorefresh.storio.sqlite.queries.InsertQuery
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_FINISH_DATE
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_LAST_CHAPTER_READ
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_LIBRARY_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_MANGA_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_MEDIA_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_SCORE
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_START_DATE
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_STATUS
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_SYNC_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TITLE
@ -54,6 +56,8 @@ class TrackPutResolver : DefaultPutResolver<Track>() {
put(COL_STATUS, obj.status)
put(COL_TRACKING_URL, obj.tracking_url)
put(COL_SCORE, obj.score)
put(COL_START_DATE, obj.started_reading_date)
put(COL_FINISH_DATE, obj.finished_reading_date)
}
}
@ -71,6 +75,8 @@ class TrackGetResolver : DefaultGetResolver<Track>() {
status = cursor.getInt(cursor.getColumnIndex(COL_STATUS))
score = cursor.getFloat(cursor.getColumnIndex(COL_SCORE))
tracking_url = cursor.getString(cursor.getColumnIndex(COL_TRACKING_URL))
started_reading_date = cursor.getLong(cursor.getColumnIndex(COL_START_DATE))
finished_reading_date = cursor.getLong(cursor.getColumnIndex(COL_FINISH_DATE))
}
}

View File

@ -26,6 +26,10 @@ interface Track : Serializable {
var tracking_url: String
var started_reading_date: Long
var finished_reading_date: Long
fun copyPersonalFrom(other: Track) {
last_chapter_read = other.last_chapter_read
score = other.score

View File

@ -24,6 +24,10 @@ class TrackImpl : Track {
override var tracking_url: String = ""
override var started_reading_date: Long = 0
override var finished_reading_date: Long = 0
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false

View File

@ -26,6 +26,10 @@ object TrackTable {
const val COL_TRACKING_URL = "remote_url"
const val COL_START_DATE = "start_date"
const val COL_FINISH_DATE = "finish_date"
val createTableQuery: String
get() =
"""CREATE TABLE $TABLE(
@ -40,6 +44,8 @@ object TrackTable {
$COL_STATUS INTEGER NOT NULL,
$COL_SCORE FLOAT NOT NULL,
$COL_TRACKING_URL TEXT NOT NULL,
$COL_START_DATE LONG NOT NULL,
$COL_FINISH_DATE LONG NOT NULL,
UNIQUE ($COL_MANGA_ID, $COL_SYNC_ID) ON CONFLICT REPLACE,
FOREIGN KEY($COL_MANGA_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID})
ON DELETE CASCADE
@ -50,4 +56,10 @@ object TrackTable {
val addLibraryId: String
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_LIBRARY_ID INTEGER NULL"
val addStartDate: String
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_START_DATE LONG NOT NULL DEFAULT 0"
val addFinishDate: String
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_FINISH_DATE LONG NOT NULL DEFAULT 0"
}

View File

@ -156,7 +156,10 @@ class PreferencesHelper(val context: Context) {
fun backupsDirectory() = flowPrefs.getString(Keys.backupDirectory, defaultBackupDir.toString())
fun dateFormat() = rxPrefs.getObject(Keys.dateFormat, DateFormat.getDateInstance(DateFormat.SHORT), DateFormatConverter())
fun dateFormat(format: String = flowPrefs.getString(Keys.dateFormat, "").get()): DateFormat = when (format) {
"" -> DateFormat.getDateInstance(DateFormat.SHORT)
else -> SimpleDateFormat(format, Locale.getDefault())
}
fun downloadsDirectory() = rxPrefs.getString(Keys.downloadsDirectory, defaultDownloadsDir.toString())

View File

@ -133,6 +133,12 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
.add("is_rereading", (track.status == MyAnimeList.REREADING).toString())
.add("score", track.score.toString())
.add("num_chapters_read", track.last_chapter_read.toString())
convertToIsoDate(track.started_reading_date)?.let {
formBodyBuilder.add("start_date", it)
}
convertToIsoDate(track.finished_reading_date)?.let {
formBodyBuilder.add("finish_date", it)
}
val request = Request.Builder()
.url(mangaUrl(track.media_id).toString())
@ -217,6 +223,12 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
status = if (isRereading) MyAnimeList.REREADING else getStatus(obj["status"]!!.jsonPrimitive.content)
last_chapter_read = obj["num_chapters_read"]!!.jsonPrimitive.int
score = obj["score"]!!.jsonPrimitive.int.toFloat()
obj["start_date"]?.let {
started_reading_date = parseDate(it.jsonPrimitive.content)
}
obj["finish_date"]?.let {
finished_reading_date = parseDate(it.jsonPrimitive.content)
}
}
}

View File

@ -883,6 +883,18 @@ class MangaDetailsPresenter(
updateRemote(track, item.service)
}
fun setTrackerStartDate(item: TrackItem, date: Long) {
val track = item.track!!
track.started_reading_date = date
updateRemote(track, item.service)
}
fun setTrackerFinishDate(item: TrackItem, date: Long) {
val track = item.track!!
track.finished_reading_date = date
updateRemote(track, item.service)
}
companion object {
const val MULTIPLE_VOLUMES = 1
const val TENS_OF_CHAPTERS = 2

View File

@ -0,0 +1,86 @@
package eu.kanade.tachiyomi.ui.manga.track
import android.app.Dialog
import android.os.Bundle
import androidx.core.os.bundleOf
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.datetime.datePicker
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
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Calendar
class SetTrackReadingDatesDialog<T> : DialogController
where T : Controller {
private val item: TrackItem
private val dateToUpdate: ReadingDate
private lateinit var listener: Listener
constructor(target: T, listener: Listener, dateToUpdate: ReadingDate, item: TrackItem) : super(
bundleOf(KEY_ITEM_TRACK to item.track)
) {
targetController = target
this.listener = listener
this.item = item
this.dateToUpdate = dateToUpdate
}
@Suppress("unused")
constructor(bundle: Bundle) : super(bundle) {
val track = bundle.getSerializable(KEY_ITEM_TRACK) as Track
val service = Injekt.get<TrackManager>().getService(track.sync_id)!!
item = TrackItem(track, service)
dateToUpdate = ReadingDate.Start
}
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
return MaterialDialog(activity!!)
.title(
when (dateToUpdate) {
ReadingDate.Start -> R.string.started_reading_date
ReadingDate.Finish -> R.string.finished_reading_date
}
)
.datePicker(currentDate = getCurrentDate()) { _, date ->
listener.setReadingDate(item, dateToUpdate, date.timeInMillis)
}
.neutralButton(R.string.remove) {
listener.setReadingDate(item, dateToUpdate, 0L)
}
}
private fun getCurrentDate(): Calendar {
// Today if no date is set, otherwise the already set date
return Calendar.getInstance().apply {
item.track?.let {
val date = when (dateToUpdate) {
ReadingDate.Start -> it.started_reading_date
ReadingDate.Finish -> it.finished_reading_date
}
if (date != 0L) {
timeInMillis = date
}
}
}
}
interface Listener {
fun setReadingDate(item: TrackItem, type: ReadingDate, date: Long)
}
enum class ReadingDate {
Start,
Finish
}
companion object {
private const val KEY_ITEM_TRACK = "SetTrackReadingDatesDialog.item.track"
}
}

View File

@ -5,13 +5,21 @@ import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.holder.BaseViewHolder
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.track_item.*
import uy.kohesive.injekt.injectLazy
import java.text.DateFormat
class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
private val preferences: PreferencesHelper by injectLazy()
private val dateFormat: DateFormat by lazy {
preferences.dateFormat()
}
init {
val listener = adapter.rowClickListener
logo_container.setOnClickListener { listener.onLogoClick(adapterPosition) }
@ -21,6 +29,8 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
track_status.setOnClickListener { listener.onStatusClick(adapterPosition) }
track_chapters.setOnClickListener { listener.onChaptersClick(adapterPosition) }
score_container.setOnClickListener { listener.onScoreClick(adapterPosition) }
track_start_date.setOnClickListener { listener.onStartDateClick(adapterPosition) }
track_finish_date.setOnClickListener { listener.onFinishDateClick(adapterPosition) }
}
@SuppressLint("SetTextI18n")
@ -59,6 +69,14 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
else track_status.text = item.service.getStatus(track.status)
track_score.text = if (track.score == 0f) "-" else item.service.displayScore(track)
track_score.setCompoundDrawablesWithIntrinsicBounds(0, 0, starIcon(track), 0)
date_group.visibleIf(item.service.supportsReadingDates)
if (item.service.supportsReadingDates) {
track_start_date.text =
if (track.started_reading_date != 0L) dateFormat.format(track.started_reading_date) else "-"
track_finish_date.text =
if (track.finished_reading_date != 0L) dateFormat.format(track.finished_reading_date) else "-"
} else {
}
}
}

View File

@ -26,7 +26,8 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
SetTrackStatusDialog.Listener,
SetTrackChaptersDialog.Listener,
SetTrackScoreDialog.Listener,
TrackRemoveDialog.Listener {
TrackRemoveDialog.Listener,
SetTrackReadingDatesDialog.Listener {
val activity = controller.activity!!
@ -182,6 +183,20 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
SetTrackScoreDialog(this, item).showDialog(controller.router)
}
override fun onStartDateClick(position: Int) {
val item = adapter?.getItem(position) ?: return
if (item.track == null) return
SetTrackReadingDatesDialog(controller, this, SetTrackReadingDatesDialog.ReadingDate.Start, item).showDialog(controller.router)
}
override fun onFinishDateClick(position: Int) {
val item = adapter?.getItem(position) ?: return
if (item.track == null) return
SetTrackReadingDatesDialog(controller, this, SetTrackReadingDatesDialog.ReadingDate.Finish, item).showDialog(controller.router)
}
override fun setStatus(item: TrackItem, selection: Int) {
presenter.setStatus(item, selection)
refreshItem(item)
@ -218,7 +233,15 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
presenter.removeTracker(item, fromServiceAlso)
}
override fun setReadingDate(item: TrackItem, type: SetTrackReadingDatesDialog.ReadingDate, date: Long) {
when (type) {
SetTrackReadingDatesDialog.ReadingDate.Start -> controller.presenter.setTrackerStartDate(item, date)
SetTrackReadingDatesDialog.ReadingDate.Finish -> controller.presenter.setTrackerFinishDate(item, date)
}
}
private companion object {
const val TAG_SEARCH_CONTROLLER = "track_search_controller"
}
}

View File

@ -39,7 +39,9 @@ class RecentlyReadAdapter(controller: RecentlyReadController) :
private val preferences: PreferencesHelper by injectLazy()
val dateFormat: DateFormat = preferences.dateFormat().getOrDefault()
val dateFormat: DateFormat by lazy {
preferences.dateFormat()
}
interface OnResumeClickListener {
fun onResumeClick(position: Int)

View File

@ -41,7 +41,9 @@ class AboutController : SettingsController() {
private val userPreferences: PreferencesHelper by injectLazy()
private val dateFormat: DateFormat = userPreferences.dateFormat().getOrDefault()
private val dateFormat: DateFormat by lazy {
preferences.dateFormat()
}
/**
* The subscribtion service of the obtained release object

View File

@ -84,7 +84,7 @@
android:layout_marginEnd="4dp"
android:contentDescription="@string/open_in_webview"
android:src="@drawable/ic_close_circle_24dp"
android:tint="@color/text_color_secondary"
app:tint="@color/text_color_secondary"
android:tooltipText="@string/remove_tracking"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@ -124,7 +124,6 @@
android:paddingTop="16dp"
android:paddingEnd="6dp"
android:paddingBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/track_chapters"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
@ -134,13 +133,14 @@
android:id="@+id/track_chapters"
style="@style/TextAppearance.Regular.Body1.Secondary"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_height="wrap_content"
android:background="@drawable/card_item_selector"
android:gravity="center"
android:maxLines="2"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="6dp"
android:paddingEnd="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/score_container"
app:layout_constraintStart_toEndOf="@id/track_status"
app:layout_constraintTop_toTopOf="parent"
@ -149,9 +149,10 @@
<FrameLayout
android:id="@+id/score_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:layout_height="wrap_content"
android:background="@drawable/card_item_selector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/track_chapters"
app:layout_constraintTop_toTopOf="parent">
@ -162,9 +163,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawableEnd="@drawable/ic_star_12dp"
android:drawableTint="?android:attr/textColorPrimary"
tools:text="10" />
app:drawableTint="?android:attr/textColorPrimary"
tools:text="10"
app:drawableEndCompat="@drawable/ic_star_12dp" />
</FrameLayout>
<View
@ -174,7 +175,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.25"
android:background="@color/strong_divider"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/bottom_divider"
app:layout_constraintEnd_toStartOf="@id/track_chapters"
app:layout_constraintStart_toEndOf="@+id/track_status"
app:layout_constraintTop_toTopOf="parent" />
@ -186,10 +187,69 @@
android:layout_marginBottom="10dp"
android:alpha="0.25"
android:background="@color/strong_divider"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/bottom_divider"
app:layout_constraintEnd_toStartOf="@id/score_container"
app:layout_constraintStart_toEndOf="@+id/track_chapters"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/bottom_divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:alpha="0.25"
android:background="@color/strong_divider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/score_container" />
<TextView
android:id="@+id/track_start_date"
style="@style/TextAppearance.Regular.Body1.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/list_item_selector"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/vert_divider_3"
app:layout_constraintTop_toBottomOf="@+id/bottom_divider"
tools:text="4/16/2020" />
<View
android:id="@+id/vert_divider_3"
android:layout_width="1dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:alpha="0.25"
android:background="@color/strong_divider"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/track_start_date"
app:layout_constraintEnd_toStartOf="@+id/track_finish_date"
app:layout_constraintTop_toTopOf="@+id/bottom_divider" />
<TextView
android:id="@+id/track_finish_date"
style="@style/TextAppearance.Regular.Body1.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/list_item_selector"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:padding="16dp"
app:layout_constraintStart_toEndOf="@+id/vert_divider_3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bottom_divider"
tools:text="4/16/2020" />
<androidx.constraintlayout.widget.Group
android:id="@+id/date_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="vert_divider_3,bottom_divider,track_start_date,track_finish_date" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.button.MaterialButton

View File

@ -433,6 +433,8 @@
<string name="kitsu" translatable="false">Kitsu</string>
<string name="bangumi" translatable="false">Bangumi</string>
<string name="shikimori" translatable="false">Shikimori</string>
<string name="started_reading_date">Started reading date</string>
<string name="finished_reading_date">Finished reading date</string>
<string name="myanimelist_relogin">Please login to MAL again</string>
<!-- Migration -->