Improve tracking search results (#1178)
* initial commit changed tracking info screen added ability to click logo to launch website * added publishing status and type to description. adjusted layout some * added start date to track info * tweaked layout * tweaked layout * tweaked layout * code review changes * code review changes part 2 * code review changes
This commit is contained in:
parent
aa7dfb7bee
commit
40b222f8bc
25 changed files with 466 additions and 107 deletions
|
@ -17,7 +17,7 @@ class DbOpenHelper(context: Context)
|
||||||
/**
|
/**
|
||||||
* Version of the database.
|
* Version of the database.
|
||||||
*/
|
*/
|
||||||
const val DATABASE_VERSION = 5
|
const val DATABASE_VERSION = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(db: SQLiteDatabase) = with(db) {
|
override fun onCreate(db: SQLiteDatabase) = with(db) {
|
||||||
|
@ -54,6 +54,9 @@ class DbOpenHelper(context: Context)
|
||||||
if (oldVersion < 5) {
|
if (oldVersion < 5) {
|
||||||
db.execSQL(ChapterTable.addScanlator)
|
db.execSQL(ChapterTable.addScanlator)
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 6) {
|
||||||
|
db.execSQL(TrackTable.addTrackingUrl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigure(db: SQLiteDatabase) {
|
override fun onConfigure(db: SQLiteDatabase) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ 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_SYNC_ID
|
||||||
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TITLE
|
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TITLE
|
||||||
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TOTAL_CHAPTERS
|
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TOTAL_CHAPTERS
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TRACKING_URL
|
||||||
import eu.kanade.tachiyomi.data.database.tables.TrackTable.TABLE
|
import eu.kanade.tachiyomi.data.database.tables.TrackTable.TABLE
|
||||||
|
|
||||||
class TrackTypeMapping : SQLiteTypeMapping<Track>(
|
class TrackTypeMapping : SQLiteTypeMapping<Track>(
|
||||||
|
@ -40,7 +41,7 @@ class TrackPutResolver : DefaultPutResolver<Track>() {
|
||||||
.whereArgs(obj.id)
|
.whereArgs(obj.id)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
override fun mapToContentValues(obj: Track) = ContentValues(9).apply {
|
override fun mapToContentValues(obj: Track) = ContentValues(10).apply {
|
||||||
put(COL_ID, obj.id)
|
put(COL_ID, obj.id)
|
||||||
put(COL_MANGA_ID, obj.manga_id)
|
put(COL_MANGA_ID, obj.manga_id)
|
||||||
put(COL_SYNC_ID, obj.sync_id)
|
put(COL_SYNC_ID, obj.sync_id)
|
||||||
|
@ -49,7 +50,9 @@ class TrackPutResolver : DefaultPutResolver<Track>() {
|
||||||
put(COL_LAST_CHAPTER_READ, obj.last_chapter_read)
|
put(COL_LAST_CHAPTER_READ, obj.last_chapter_read)
|
||||||
put(COL_TOTAL_CHAPTERS, obj.total_chapters)
|
put(COL_TOTAL_CHAPTERS, obj.total_chapters)
|
||||||
put(COL_STATUS, obj.status)
|
put(COL_STATUS, obj.status)
|
||||||
|
put(COL_TRACKING_URL, obj.tracking_url)
|
||||||
put(COL_SCORE, obj.score)
|
put(COL_SCORE, obj.score)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +68,7 @@ class TrackGetResolver : DefaultGetResolver<Track>() {
|
||||||
total_chapters = cursor.getInt(cursor.getColumnIndex(COL_TOTAL_CHAPTERS))
|
total_chapters = cursor.getInt(cursor.getColumnIndex(COL_TOTAL_CHAPTERS))
|
||||||
status = cursor.getInt(cursor.getColumnIndex(COL_STATUS))
|
status = cursor.getInt(cursor.getColumnIndex(COL_STATUS))
|
||||||
score = cursor.getFloat(cursor.getColumnIndex(COL_SCORE))
|
score = cursor.getFloat(cursor.getColumnIndex(COL_SCORE))
|
||||||
|
tracking_url = cursor.getString(cursor.getColumnIndex(COL_TRACKING_URL))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ interface Track : Serializable {
|
||||||
|
|
||||||
var status: Int
|
var status: Int
|
||||||
|
|
||||||
|
var tracking_url: String
|
||||||
|
|
||||||
fun copyPersonalFrom(other: Track) {
|
fun copyPersonalFrom(other: Track) {
|
||||||
last_chapter_read = other.last_chapter_read
|
last_chapter_read = other.last_chapter_read
|
||||||
score = other.score
|
score = other.score
|
||||||
|
@ -29,7 +31,6 @@ interface Track : Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun create(serviceId: Int): Track = TrackImpl().apply {
|
fun create(serviceId: Int): Track = TrackImpl().apply {
|
||||||
sync_id = serviceId
|
sync_id = serviceId
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ class TrackImpl : Track {
|
||||||
|
|
||||||
override var status: Int = 0
|
override var status: Int = 0
|
||||||
|
|
||||||
|
override lateinit var tracking_url: String
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other == null || javaClass != other.javaClass) return false
|
if (other == null || javaClass != other.javaClass) return false
|
||||||
|
|
|
@ -22,6 +22,8 @@ object TrackTable {
|
||||||
|
|
||||||
const val COL_TOTAL_CHAPTERS = "total_chapters"
|
const val COL_TOTAL_CHAPTERS = "total_chapters"
|
||||||
|
|
||||||
|
const val COL_TRACKING_URL = "remote_url"
|
||||||
|
|
||||||
val createTableQuery: String
|
val createTableQuery: String
|
||||||
get() = """CREATE TABLE $TABLE(
|
get() = """CREATE TABLE $TABLE(
|
||||||
$COL_ID INTEGER NOT NULL PRIMARY KEY,
|
$COL_ID INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
@ -33,9 +35,12 @@ object TrackTable {
|
||||||
$COL_TOTAL_CHAPTERS INTEGER NOT NULL,
|
$COL_TOTAL_CHAPTERS INTEGER NOT NULL,
|
||||||
$COL_STATUS INTEGER NOT NULL,
|
$COL_STATUS INTEGER NOT NULL,
|
||||||
$COL_SCORE FLOAT NOT NULL,
|
$COL_SCORE FLOAT NOT NULL,
|
||||||
|
$COL_TRACKING_URL TEXT NOT NULL,
|
||||||
UNIQUE ($COL_MANGA_ID, $COL_SYNC_ID) ON CONFLICT REPLACE,
|
UNIQUE ($COL_MANGA_ID, $COL_SYNC_ID) ON CONFLICT REPLACE,
|
||||||
FOREIGN KEY($COL_MANGA_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID})
|
FOREIGN KEY($COL_MANGA_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID})
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
)"""
|
)"""
|
||||||
|
|
||||||
|
val addTrackingUrl: String
|
||||||
|
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_TRACKING_URL TEXT DEFAULT ''"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.track
|
||||||
import android.support.annotation.CallSuper
|
import android.support.annotation.CallSuper
|
||||||
import android.support.annotation.DrawableRes
|
import android.support.annotation.DrawableRes
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -44,7 +45,7 @@ abstract class TrackService(val id: Int) {
|
||||||
|
|
||||||
abstract fun bind(track: Track): Observable<Track>
|
abstract fun bind(track: Track): Observable<Track>
|
||||||
|
|
||||||
abstract fun search(query: String): Observable<List<Track>>
|
abstract fun search(query: String): Observable<List<TrackSearch>>
|
||||||
|
|
||||||
abstract fun refresh(track: Track): Observable<Track>
|
abstract fun refresh(track: Track): Observable<Track>
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun search(query: String): Observable<List<Track>> {
|
override fun search(query: String): Observable<List<TrackSearch>> {
|
||||||
return api.search(query)
|
return api.search(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.github.salomonbrys.kotson.int
|
||||||
import com.github.salomonbrys.kotson.string
|
import com.github.salomonbrys.kotson.string
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -46,7 +47,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(query: String): Observable<List<Track>> {
|
fun search(query: String): Observable<List<TrackSearch>> {
|
||||||
return rest.search(query, 1)
|
return rest.search(query, 1)
|
||||||
.map { list ->
|
.map { list ->
|
||||||
list.filter { it.type != "Novel" }.map { it.toTrack() }
|
list.filter { it.type != "Novel" }.map { it.toTrack() }
|
||||||
|
@ -140,6 +141,11 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
private const val clientSecret = "nlGB5OmgE9YWq5dr3gIDbTQV0C"
|
private const val clientSecret = "nlGB5OmgE9YWq5dr3gIDbTQV0C"
|
||||||
private const val clientUrl = "tachiyomi://anilist-auth"
|
private const val clientUrl = "tachiyomi://anilist-auth"
|
||||||
private const val baseUrl = "https://anilist.co/api/"
|
private const val baseUrl = "https://anilist.co/api/"
|
||||||
|
private const val baseMangaUrl = "https://anilist.co/manga/"
|
||||||
|
|
||||||
|
fun mangaUrl(remoteId: Int): String {
|
||||||
|
return baseMangaUrl + remoteId
|
||||||
|
}
|
||||||
|
|
||||||
fun authUrl() = Uri.parse("${baseUrl}auth/authorize").buildUpon()
|
fun authUrl() = Uri.parse("${baseUrl}auth/authorize").buildUpon()
|
||||||
.appendQueryParameter("grant_type", "authorization_code")
|
.appendQueryParameter("grant_type", "authorization_code")
|
||||||
|
|
|
@ -1,21 +1,45 @@
|
||||||
package eu.kanade.tachiyomi.data.track.anilist
|
package eu.kanade.tachiyomi.data.track.anilist
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
data class ALManga(
|
data class ALManga(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val title_romaji: String,
|
val title_romaji: String,
|
||||||
|
val image_url_lge: String,
|
||||||
|
val description: String,
|
||||||
val type: String,
|
val type: String,
|
||||||
|
val publishing_status: String,
|
||||||
|
val start_date_fuzzy: String,
|
||||||
val total_chapters: Int) {
|
val total_chapters: Int) {
|
||||||
|
|
||||||
fun toTrack() = Track.create(TrackManager.ANILIST).apply {
|
fun toTrack() = TrackSearch.create(TrackManager.ANILIST).apply {
|
||||||
remote_id = this@ALManga.id
|
remote_id = this@ALManga.id
|
||||||
title = title_romaji
|
title = title_romaji
|
||||||
total_chapters = this@ALManga.total_chapters
|
total_chapters = this@ALManga.total_chapters
|
||||||
|
cover_url = image_url_lge
|
||||||
|
summary = description
|
||||||
|
tracking_url = AnilistApi.mangaUrl(remote_id)
|
||||||
|
publishing_status = this@ALManga.publishing_status
|
||||||
|
publishing_type = type
|
||||||
|
if (!start_date_fuzzy.isNullOrBlank()) {
|
||||||
|
start_date = try {
|
||||||
|
val inputDf = SimpleDateFormat("yyyyMMdd", Locale.US)
|
||||||
|
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||||
|
val date = inputDf.parse(BuildConfig.BUILD_TIME)
|
||||||
|
outputDf.format(date)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
start_date_fuzzy.orEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,11 +84,11 @@ fun Track.toAnilistStatus() = when (status) {
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
fun Track.toAnilistScore(): String = when (preferences.anilistScoreType().getOrDefault()) {
|
fun Track.toAnilistScore(): String = when (preferences.anilistScoreType().getOrDefault()) {
|
||||||
// 10 point
|
// 10 point
|
||||||
0 -> (score.toInt() / 10).toString()
|
0 -> (score.toInt() / 10).toString()
|
||||||
// 100 point
|
// 100 point
|
||||||
1 -> score.toInt().toString()
|
1 -> score.toInt().toString()
|
||||||
// 5 stars
|
// 5 stars
|
||||||
2 -> when {
|
2 -> when {
|
||||||
score == 0f -> "0"
|
score == 0f -> "0"
|
||||||
score < 30 -> "1"
|
score < 30 -> "1"
|
||||||
|
@ -73,14 +97,14 @@ fun Track.toAnilistScore(): String = when (preferences.anilistScoreType().getOrD
|
||||||
score < 90 -> "4"
|
score < 90 -> "4"
|
||||||
else -> "5"
|
else -> "5"
|
||||||
}
|
}
|
||||||
// Smiley
|
// Smiley
|
||||||
3 -> when {
|
3 -> when {
|
||||||
score == 0f -> "0"
|
score == 0f -> "0"
|
||||||
score <= 30 -> ":("
|
score <= 30 -> ":("
|
||||||
score <= 60 -> ":|"
|
score <= 60 -> ":|"
|
||||||
else -> ":)"
|
else -> ":)"
|
||||||
}
|
}
|
||||||
// 10 point decimal
|
// 10 point decimal
|
||||||
4 -> (score / 10).toString()
|
4 -> (score / 10).toString()
|
||||||
else -> throw Exception("Unknown score type")
|
else -> throw Exception("Unknown score type")
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ import com.google.gson.Gson
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
@ -96,7 +97,7 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun search(query: String): Observable<List<Track>> {
|
override fun search(query: String): Observable<List<TrackSearch>> {
|
||||||
return api.search(query)
|
return api.search(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.github.salomonbrys.kotson.*
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -27,25 +28,25 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
return Observable.defer {
|
return Observable.defer {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
val data = jsonObject(
|
val data = jsonObject(
|
||||||
"type" to "libraryEntries",
|
"type" to "libraryEntries",
|
||||||
"attributes" to jsonObject(
|
"attributes" to jsonObject(
|
||||||
"status" to track.toKitsuStatus(),
|
"status" to track.toKitsuStatus(),
|
||||||
"progress" to track.last_chapter_read
|
"progress" to track.last_chapter_read
|
||||||
),
|
|
||||||
"relationships" to jsonObject(
|
|
||||||
"user" to jsonObject(
|
|
||||||
"data" to jsonObject(
|
|
||||||
"id" to userId,
|
|
||||||
"type" to "users"
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
"media" to jsonObject(
|
"relationships" to jsonObject(
|
||||||
"data" to jsonObject(
|
"user" to jsonObject(
|
||||||
"id" to track.remote_id,
|
"data" to jsonObject(
|
||||||
"type" to "manga"
|
"id" to userId,
|
||||||
)
|
"type" to "users"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
"media" to jsonObject(
|
||||||
|
"data" to jsonObject(
|
||||||
|
"id" to track.remote_id,
|
||||||
|
"type" to "manga"
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
|
@ -61,13 +62,13 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
return Observable.defer {
|
return Observable.defer {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
val data = jsonObject(
|
val data = jsonObject(
|
||||||
"type" to "libraryEntries",
|
"type" to "libraryEntries",
|
||||||
"id" to track.remote_id,
|
"id" to track.remote_id,
|
||||||
"attributes" to jsonObject(
|
"attributes" to jsonObject(
|
||||||
"status" to track.toKitsuStatus(),
|
"status" to track.toKitsuStatus(),
|
||||||
"progress" to track.last_chapter_read,
|
"progress" to track.last_chapter_read,
|
||||||
"ratingTwenty" to track.toKitsuScore()
|
"ratingTwenty" to track.toKitsuScore()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(query: String): Observable<List<Track>> {
|
fun search(query: String): Observable<List<TrackSearch>> {
|
||||||
return rest.search(query)
|
return rest.search(query)
|
||||||
.map { json ->
|
.map { json ->
|
||||||
val data = json["data"].array
|
val data = json["data"].array
|
||||||
|
@ -186,6 +187,11 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
private const val clientSecret = "54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
private const val clientSecret = "54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
||||||
private const val baseUrl = "https://kitsu.io/api/edge/"
|
private const val baseUrl = "https://kitsu.io/api/edge/"
|
||||||
private const val loginUrl = "https://kitsu.io/api/"
|
private const val loginUrl = "https://kitsu.io/api/"
|
||||||
|
private const val baseMangaUrl = "https://kitsu.io/manga/"
|
||||||
|
|
||||||
|
fun mangaUrl(remoteId: Int): String {
|
||||||
|
return baseMangaUrl + remoteId
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun refreshTokenRequest(token: String) = POST("${loginUrl}oauth/token",
|
fun refreshTokenRequest(token: String) = POST("${loginUrl}oauth/token",
|
||||||
|
|
|
@ -5,24 +5,35 @@ import com.github.salomonbrys.kotson.*
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
|
|
||||||
open class KitsuManga(obj: JsonObject) {
|
open class KitsuManga(obj: JsonObject) {
|
||||||
val id by obj.byInt
|
val id by obj.byInt
|
||||||
val canonicalTitle by obj["attributes"].byString
|
val canonicalTitle by obj["attributes"].byString
|
||||||
val chapterCount = obj["attributes"].obj.get("chapterCount").nullInt
|
val chapterCount = obj["attributes"].obj.get("chapterCount").nullInt
|
||||||
val type = obj["attributes"].obj.get("mangaType").nullString
|
val type = obj["attributes"].obj.get("mangaType").nullString.orEmpty()
|
||||||
|
val original by obj["attributes"].obj["posterImage"].byString
|
||||||
|
val synopsis by obj["attributes"].byString
|
||||||
|
val startDate = obj["attributes"].obj.get("startDate").nullString.orEmpty()
|
||||||
|
val status = obj["attributes"].obj.get("status").nullString.orEmpty()
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
open fun toTrack() = Track.create(TrackManager.KITSU).apply {
|
open fun toTrack() = TrackSearch.create(TrackManager.KITSU).apply {
|
||||||
remote_id = this@KitsuManga.id
|
remote_id = this@KitsuManga.id
|
||||||
title = canonicalTitle
|
title = canonicalTitle
|
||||||
total_chapters = chapterCount ?: 0
|
total_chapters = chapterCount ?: 0
|
||||||
|
cover_url = original
|
||||||
|
summary = synopsis
|
||||||
|
tracking_url = KitsuApi.mangaUrl(remote_id)
|
||||||
|
publishing_status = this@KitsuManga.status
|
||||||
|
publishing_type = type
|
||||||
|
start_date = startDate.orEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KitsuLibManga(obj: JsonObject, manga: JsonObject) : KitsuManga(manga) {
|
class KitsuLibManga(obj: JsonObject, manga: JsonObject) : KitsuManga(manga) {
|
||||||
val remoteId by obj.byInt("id")
|
val remoteId by obj.byInt("id")
|
||||||
val status by obj["attributes"].byString
|
//override val status by obj["attributes"].byString
|
||||||
val ratingTwenty = obj["attributes"].obj.get("ratingTwenty").nullString
|
val ratingTwenty = obj["attributes"].obj.get("ratingTwenty").nullString
|
||||||
val progress by obj["attributes"].byInt
|
val progress by obj["attributes"].byInt
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package eu.kanade.tachiyomi.data.track.model
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
|
||||||
|
class TrackSearch : Track {
|
||||||
|
|
||||||
|
override var id: Long? = null
|
||||||
|
|
||||||
|
override var manga_id: Long = 0
|
||||||
|
|
||||||
|
override var sync_id: Int = 0
|
||||||
|
|
||||||
|
override var remote_id: Int = 0
|
||||||
|
|
||||||
|
override lateinit var title: String
|
||||||
|
|
||||||
|
override var last_chapter_read: Int = 0
|
||||||
|
|
||||||
|
override var total_chapters: Int = 0
|
||||||
|
|
||||||
|
override var score: Float = 0f
|
||||||
|
|
||||||
|
override var status: Int = 0
|
||||||
|
|
||||||
|
override lateinit var tracking_url: String
|
||||||
|
|
||||||
|
var cover_url: String = ""
|
||||||
|
|
||||||
|
var summary: String = ""
|
||||||
|
|
||||||
|
var publishing_status: String = ""
|
||||||
|
|
||||||
|
var publishing_type: String = ""
|
||||||
|
|
||||||
|
var start_date: String = ""
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other == null || javaClass != other.javaClass) return false
|
||||||
|
|
||||||
|
other as Track
|
||||||
|
|
||||||
|
if (manga_id != other.manga_id) return false
|
||||||
|
if (sync_id != other.sync_id) return false
|
||||||
|
return remote_id == other.remote_id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = (manga_id xor manga_id.ushr(32)).toInt()
|
||||||
|
result = 31 * result + sync_id
|
||||||
|
result = 31 * result + remote_id
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun create(serviceId: Int): TrackSearch = TrackSearch().apply {
|
||||||
|
sync_id = serviceId
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
@ -81,7 +82,7 @@ class Myanimelist(private val context: Context, id: Int) : TrackService(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun search(query: String): Observable<List<Track>> {
|
override fun search(query: String): Observable<List<TrackSearch>> {
|
||||||
return api.search(query, getUsername())
|
return api.search(query, getUsername())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.net.Uri
|
||||||
import android.util.Xml
|
import android.util.Xml
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.asObservable
|
import eu.kanade.tachiyomi.network.asObservable
|
||||||
|
@ -12,6 +13,7 @@ import eu.kanade.tachiyomi.util.selectInt
|
||||||
import eu.kanade.tachiyomi.util.selectText
|
import eu.kanade.tachiyomi.util.selectText
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.parser.Parser
|
||||||
import org.xmlpull.v1.XmlSerializer
|
import org.xmlpull.v1.XmlSerializer
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
|
@ -36,7 +38,7 @@ class MyanimelistApi(private val client: OkHttpClient, username: String, passwor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(query: String, username: String): Observable<List<Track>> {
|
fun search(query: String, username: String): Observable<List<TrackSearch>> {
|
||||||
return if (query.startsWith(PREFIX_MY)) {
|
return if (query.startsWith(PREFIX_MY)) {
|
||||||
val realQuery = query.substring(PREFIX_MY.length).toLowerCase().trim()
|
val realQuery = query.substring(PREFIX_MY.length).toLowerCase().trim()
|
||||||
getList(username)
|
getList(username)
|
||||||
|
@ -46,34 +48,42 @@ class MyanimelistApi(private val client: OkHttpClient, username: String, passwor
|
||||||
} else {
|
} else {
|
||||||
client.newCall(GET(getSearchUrl(query), headers))
|
client.newCall(GET(getSearchUrl(query), headers))
|
||||||
.asObservable()
|
.asObservable()
|
||||||
.map { Jsoup.parse(it.body()!!.string()) }
|
.map { Jsoup.parse(Parser.unescapeEntities(it.body()!!.string(), false), "", Parser.xmlParser()) }
|
||||||
.flatMap { Observable.from(it.select("entry")) }
|
.flatMap { Observable.from(it.select("entry")) }
|
||||||
.filter { it.select("type").text() != "Novel" }
|
.filter { it.select("type").text() != "Novel" }
|
||||||
.map {
|
.map {
|
||||||
Track.create(TrackManager.MYANIMELIST).apply {
|
TrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||||
title = it.selectText("title")!!
|
title = it.selectText("title")!!
|
||||||
remote_id = it.selectInt("id")
|
remote_id = it.selectInt("id")
|
||||||
total_chapters = it.selectInt("chapters")
|
total_chapters = it.selectInt("chapters")
|
||||||
|
summary = it.selectText("synopsis")!!
|
||||||
|
cover_url = it.selectText("image")!!
|
||||||
|
tracking_url = MyanimelistApi.mangaUrl(remote_id)
|
||||||
|
publishing_status = it.selectText("status")!!
|
||||||
|
publishing_type = it.selectText("type")!!
|
||||||
|
start_date = it.selectText("start_date")!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getList(username: String): Observable<List<Track>> {
|
fun getList(username: String): Observable<List<TrackSearch>> {
|
||||||
return client
|
return client
|
||||||
.newCall(GET(getListUrl(username), headers))
|
.newCall(GET(getListUrl(username), headers))
|
||||||
.asObservable()
|
.asObservable()
|
||||||
.map { Jsoup.parse(it.body()!!.string()) }
|
.map { Jsoup.parse(Parser.unescapeEntities(it.body()!!.string(), false), "", Parser.xmlParser()) }
|
||||||
.flatMap { Observable.from(it.select("manga")) }
|
.flatMap { Observable.from(it.select("manga")) }
|
||||||
.map {
|
.map {
|
||||||
Track.create(TrackManager.MYANIMELIST).apply {
|
TrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||||
title = it.selectText("series_title")!!
|
title = it.selectText("series_title")!!
|
||||||
remote_id = it.selectInt("series_mangadb_id")
|
remote_id = it.selectInt("series_mangadb_id")
|
||||||
last_chapter_read = it.selectInt("my_read_chapters")
|
last_chapter_read = it.selectInt("my_read_chapters")
|
||||||
status = it.selectInt("my_status")
|
status = it.selectInt("my_status")
|
||||||
score = it.selectInt("my_score").toFloat()
|
score = it.selectInt("my_score").toFloat()
|
||||||
total_chapters = it.selectInt("series_chapters")
|
total_chapters = it.selectInt("series_chapters")
|
||||||
|
cover_url = it.selectText("series_image")!!
|
||||||
|
tracking_url = MyanimelistApi.mangaUrl(remote_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
|
@ -176,6 +186,11 @@ class MyanimelistApi(private val client: OkHttpClient, username: String, passwor
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val baseUrl = "https://myanimelist.net"
|
const val baseUrl = "https://myanimelist.net"
|
||||||
|
const val baseMangaUrl = baseUrl + "/manga/"
|
||||||
|
|
||||||
|
fun mangaUrl(remoteId: Int): String {
|
||||||
|
return baseMangaUrl + remoteId
|
||||||
|
}
|
||||||
|
|
||||||
private val ENTRY_TAG = "entry"
|
private val ENTRY_TAG = "entry"
|
||||||
private val CHAPTER_TAG = "chapter"
|
private val CHAPTER_TAG = "chapter"
|
||||||
|
|
|
@ -15,7 +15,7 @@ class TrackAdapter(controller: TrackController) : RecyclerView.Adapter<TrackHold
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val rowClickListener: OnRowClickListener = controller
|
val rowClickListener: OnClickListener = controller
|
||||||
|
|
||||||
fun getItem(index: Int): TrackItem? {
|
fun getItem(index: Int): TrackItem? {
|
||||||
return items.getOrNull(index)
|
return items.getOrNull(index)
|
||||||
|
@ -34,7 +34,8 @@ class TrackAdapter(controller: TrackController) : RecyclerView.Adapter<TrackHold
|
||||||
holder.bind(items[position])
|
holder.bind(items[position])
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OnRowClickListener {
|
interface OnClickListener {
|
||||||
|
fun onLogoClick(position: Int)
|
||||||
fun onTitleClick(position: Int)
|
fun onTitleClick(position: Int)
|
||||||
fun onStatusClick(position: Int)
|
fun onStatusClick(position: Int)
|
||||||
fun onChaptersClick(position: Int)
|
fun onChaptersClick(position: Int)
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
package eu.kanade.tachiyomi.ui.manga.track
|
package eu.kanade.tachiyomi.ui.manga.track
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import android.support.v7.widget.LinearLayoutManager
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.util.toast
|
import eu.kanade.tachiyomi.util.toast
|
||||||
import kotlinx.android.synthetic.main.track_controller.*
|
import kotlinx.android.synthetic.main.track_controller.*
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
class TrackController : NucleusController<TrackPresenter>(),
|
class TrackController : NucleusController<TrackPresenter>(),
|
||||||
TrackAdapter.OnRowClickListener,
|
TrackAdapter.OnClickListener,
|
||||||
SetTrackStatusDialog.Listener,
|
SetTrackStatusDialog.Listener,
|
||||||
SetTrackChaptersDialog.Listener,
|
SetTrackChaptersDialog.Listener,
|
||||||
SetTrackScoreDialog.Listener {
|
SetTrackScoreDialog.Listener {
|
||||||
|
@ -58,12 +61,13 @@ class TrackController : NucleusController<TrackPresenter>(),
|
||||||
(parentController as? MangaController)?.setTrackingIcon(atLeastOneLink)
|
(parentController as? MangaController)?.setTrackingIcon(atLeastOneLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSearchResults(results: List<Track>) {
|
fun onSearchResults(results: List<TrackSearch>) {
|
||||||
getSearchDialog()?.onSearchResults(results)
|
getSearchDialog()?.onSearchResults(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
fun onSearchResultsError(error: Throwable) {
|
fun onSearchResultsError(error: Throwable) {
|
||||||
|
Timber.e(error)
|
||||||
getSearchDialog()?.onSearchResultsError()
|
getSearchDialog()?.onSearchResultsError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +84,16 @@ class TrackController : NucleusController<TrackPresenter>(),
|
||||||
activity?.toast(error.message)
|
activity?.toast(error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onLogoClick(position: Int) {
|
||||||
|
val track = adapter?.getItem(position)?.track ?: return
|
||||||
|
|
||||||
|
if (track.tracking_url.isNullOrBlank()) {
|
||||||
|
activity?.toast(R.string.url_not_set)
|
||||||
|
} else {
|
||||||
|
activity?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(track.tracking_url)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTitleClick(position: Int) {
|
override fun onTitleClick(position: Int) {
|
||||||
val item = adapter?.getItem(position) ?: return
|
val item = adapter?.getItem(position) ?: return
|
||||||
TrackSearchDialog(this, item.service).showDialog(router, TAG_SEARCH_CONTROLLER)
|
TrackSearchDialog(this, item.service).showDialog(router, TAG_SEARCH_CONTROLLER)
|
||||||
|
|
|
@ -7,9 +7,10 @@ import eu.kanade.tachiyomi.ui.base.holder.BaseViewHolder
|
||||||
import kotlinx.android.synthetic.main.track_item.*
|
import kotlinx.android.synthetic.main.track_item.*
|
||||||
|
|
||||||
class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val listener = adapter.rowClickListener
|
val listener = adapter.rowClickListener
|
||||||
|
logo_container.setOnClickListener { listener.onLogoClick(adapterPosition) }
|
||||||
title_container.setOnClickListener { listener.onTitleClick(adapterPosition) }
|
title_container.setOnClickListener { listener.onTitleClick(adapterPosition) }
|
||||||
status_container.setOnClickListener { listener.onStatusClick(adapterPosition) }
|
status_container.setOnClickListener { listener.onStatusClick(adapterPosition) }
|
||||||
chapters_container.setOnClickListener { listener.onChaptersClick(adapterPosition) }
|
chapters_container.setOnClickListener { listener.onChaptersClick(adapterPosition) }
|
||||||
|
@ -21,7 +22,7 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
||||||
fun bind(item: TrackItem) {
|
fun bind(item: TrackItem) {
|
||||||
val track = item.track
|
val track = item.track
|
||||||
track_logo.setImageResource(item.service.getLogo())
|
track_logo.setImageResource(item.service.getLogo())
|
||||||
logo.setBackgroundColor(item.service.getLogoColor())
|
logo_container.setBackgroundColor(item.service.getLogoColor())
|
||||||
if (track != null) {
|
if (track != null) {
|
||||||
track_title.setTextAppearance(itemView.context, R.style.TextAppearance_Regular_Body1_Secondary)
|
track_title.setTextAppearance(itemView.context, R.style.TextAppearance_Regular_Body1_Secondary)
|
||||||
track_title.setAllCaps(false)
|
track_title.setAllCaps(false)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
|
||||||
class TrackPresenter(
|
class TrackPresenter(
|
||||||
val manga: Manga,
|
val manga: Manga,
|
||||||
preferences: PreferencesHelper = Injekt.get(),
|
preferences: PreferencesHelper = Injekt.get(),
|
||||||
|
|
|
@ -4,14 +4,17 @@ import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
|
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||||
|
import eu.kanade.tachiyomi.util.gone
|
||||||
import eu.kanade.tachiyomi.util.inflate
|
import eu.kanade.tachiyomi.util.inflate
|
||||||
import kotlinx.android.synthetic.main.track_search_item.view.*
|
import kotlinx.android.synthetic.main.track_search_item.view.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class TrackSearchAdapter(context: Context)
|
class TrackSearchAdapter(context: Context)
|
||||||
: ArrayAdapter<Track>(context, R.layout.track_search_item, ArrayList<Track>()) {
|
: ArrayAdapter<TrackSearch>(context, R.layout.track_search_item, ArrayList<TrackSearch>()) {
|
||||||
|
|
||||||
override fun getView(position: Int, view: View?, parent: ViewGroup): View {
|
override fun getView(position: Int, view: View?, parent: ViewGroup): View {
|
||||||
var v = view
|
var v = view
|
||||||
|
@ -30,7 +33,7 @@ class TrackSearchAdapter(context: Context)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setItems(syncs: List<Track>) {
|
fun setItems(syncs: List<TrackSearch>) {
|
||||||
setNotifyOnChange(false)
|
setNotifyOnChange(false)
|
||||||
clear()
|
clear()
|
||||||
addAll(syncs)
|
addAll(syncs)
|
||||||
|
@ -39,8 +42,40 @@ class TrackSearchAdapter(context: Context)
|
||||||
|
|
||||||
class TrackSearchHolder(private val view: View) {
|
class TrackSearchHolder(private val view: View) {
|
||||||
|
|
||||||
fun onSetValues(track: Track) {
|
fun onSetValues(track: TrackSearch) {
|
||||||
view.track_search_title.text = track.title
|
view.track_search_title.text = track.title
|
||||||
|
view.track_search_summary.text = track.summary
|
||||||
|
GlideApp.with(view.context).clear(view.track_search_cover)
|
||||||
|
if (!track.cover_url.isNullOrEmpty()) {
|
||||||
|
GlideApp.with(view.context)
|
||||||
|
.load(track.cover_url)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||||
|
.centerCrop()
|
||||||
|
.into(view.track_search_cover)
|
||||||
|
|
||||||
|
|
||||||
|
if (track.publishing_status.isNullOrBlank()) {
|
||||||
|
view.track_search_status.gone()
|
||||||
|
view.track_search_status_result.gone()
|
||||||
|
} else {
|
||||||
|
view.track_search_status_result.text = track.publishing_status.capitalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track.publishing_type.isNullOrBlank()) {
|
||||||
|
view.track_search_type.gone()
|
||||||
|
view.track_search_type_result.gone()
|
||||||
|
} else {
|
||||||
|
view.track_search_type_result.text = track.publishing_type.capitalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track.start_date.isNullOrBlank()) {
|
||||||
|
view.track_search_start.gone()
|
||||||
|
view.track_search_start_result.gone()
|
||||||
|
} else {
|
||||||
|
view.track_search_start_result.text = track.start_date
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import com.jakewharton.rxbinding.widget.itemClicks
|
||||||
import com.jakewharton.rxbinding.widget.textChanges
|
import com.jakewharton.rxbinding.widget.textChanges
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
|
@ -114,11 +115,10 @@ class TrackSearchDialog : DialogController {
|
||||||
val view = dialogView ?: return
|
val view = dialogView ?: return
|
||||||
view.progress.visibility = View.VISIBLE
|
view.progress.visibility = View.VISIBLE
|
||||||
view.track_search_list.visibility = View.GONE
|
view.track_search_list.visibility = View.GONE
|
||||||
|
|
||||||
trackController.presenter.search(query, service)
|
trackController.presenter.search(query, service)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSearchResults(results: List<Track>) {
|
fun onSearchResults(results: List<TrackSearch>) {
|
||||||
selectedItem = null
|
selectedItem = null
|
||||||
val view = dialogView ?: return
|
val view = dialogView ?: return
|
||||||
view.progress.visibility = View.GONE
|
view.progress.visibility = View.GONE
|
||||||
|
|
|
@ -11,12 +11,13 @@
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/logo"
|
android:id="@+id/logo_container"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:clickable="true"
|
||||||
tools:background="#2E51A2">
|
tools:background="#2E51A2">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
android:background="?attr/selectable_list_drawable"
|
android:background="?attr/selectable_list_drawable"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/logo"
|
app:layout_constraintLeft_toRightOf="@+id/logo_container"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:background="?android:attr/divider"
|
android:background="?android:attr/divider"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/logo"
|
app:layout_constraintLeft_toRightOf="@+id/logo_container"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/title_container" />
|
app:layout_constraintTop_toBottomOf="@+id/title_container" />
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@
|
||||||
android:background="?attr/selectable_list_drawable"
|
android:background="?attr/selectable_list_drawable"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/logo"
|
app:layout_constraintLeft_toRightOf="@+id/logo_container"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/divider1">
|
app:layout_constraintTop_toBottomOf="@+id/divider1">
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:background="?android:attr/divider"
|
android:background="?android:attr/divider"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/logo"
|
app:layout_constraintLeft_toRightOf="@+id/logo_container"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/status_container" />
|
app:layout_constraintTop_toBottomOf="@+id/status_container" />
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@
|
||||||
android:background="?attr/selectable_list_drawable"
|
android:background="?attr/selectable_list_drawable"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/logo"
|
app:layout_constraintLeft_toRightOf="@+id/logo_container"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/divider2">
|
app:layout_constraintTop_toBottomOf="@+id/divider2">
|
||||||
|
|
||||||
|
@ -152,7 +153,7 @@
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:background="?android:attr/divider"
|
android:background="?android:attr/divider"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/logo"
|
app:layout_constraintLeft_toRightOf="@+id/logo_container"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chapters_container" />
|
app:layout_constraintTop_toBottomOf="@+id/chapters_container" />
|
||||||
|
|
||||||
|
@ -163,7 +164,7 @@
|
||||||
android:background="?attr/selectable_list_drawable"
|
android:background="?attr/selectable_list_drawable"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/logo"
|
app:layout_constraintLeft_toRightOf="@+id/logo_container"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/divider3">
|
app:layout_constraintTop_toBottomOf="@+id/divider3">
|
||||||
|
|
||||||
|
|
|
@ -1,47 +1,64 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<EditText
|
||||||
|
android:id="@+id/track_search"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:hint="@string/title"
|
||||||
android:orientation="horizontal"
|
android:layout_marginEnd="16dp"
|
||||||
android:paddingLeft="@dimen/margin_left"
|
android:layout_marginStart="16dp"
|
||||||
android:paddingRight="@dimen/margin_right">
|
app:layout_constraintTop_toTopOf="parent"/>
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/track_search"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:hint="@string/title"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress"
|
android:id="@+id/progress"
|
||||||
style="?android:attr/progressBarStyle"
|
style="?android:attr/progressBarStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical|center_horizontal"
|
android:layout_marginBottom="32dp"
|
||||||
android:paddingBottom="32dp"
|
android:layout_marginTop="32dp"
|
||||||
android:paddingTop="32dp"
|
android:visibility="gone"
|
||||||
android:visibility="gone"/>
|
app:layout_constraintBottom_toTopOf="@id/divider1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/track_search"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/track_search_list"
|
android:id="@+id/track_search_list"
|
||||||
|
style="@style/Theme.Widget.CardView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
android:choiceMode="singleChoice"
|
android:choiceMode="singleChoice"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:divider="@null"
|
android:divider="@null"
|
||||||
android:dividerHeight="0dp"
|
android:dividerHeight="10dp"
|
||||||
|
android:footerDividersEnabled="true"
|
||||||
|
android:headerDividersEnabled="true"
|
||||||
android:listSelector="?attr/selectable_list_drawable"
|
android:listSelector="?attr/selectable_list_drawable"
|
||||||
android:scrollbarStyle="outsideOverlay"
|
android:paddingBottom="4dp"
|
||||||
android:visibility="gone"/>
|
android:paddingTop="4dp"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/track_search"
|
||||||
|
tools:listitem="@layout/track_search_item"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
</LinearLayout>
|
<View
|
||||||
|
android:id="@+id/divider1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?android:attr/divider"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/track_search_list"/>
|
||||||
|
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
|
@ -1,14 +1,155 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.v7.widget.CardView android:id="@+id/cv_manga"
|
||||||
android:layout_width="match_parent"
|
style="@style/Theme.Widget.CardView.Item"
|
||||||
android:layout_height="wrap_content"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:background="?attr/selectable_list_drawable">
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:padding="0dp">
|
||||||
|
|
||||||
<TextView
|
<android.support.constraint.ConstraintLayout
|
||||||
android:id="@+id/track_search_title"
|
android:id="@+id/linearLayout"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="216dp"
|
||||||
android:padding="10dp"/>
|
android:background="?attr/selectable_list_drawable"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
>
|
||||||
|
|
||||||
</LinearLayout>
|
<ImageView
|
||||||
|
android:id="@+id/track_search_cover"
|
||||||
|
android:layout_width="135dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:contentDescription="@string/description_cover"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.0"
|
||||||
|
tools:src="@drawable/branded_logo_icon"/>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Bold"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_cover"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="One Piece"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_type"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/track_type"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Bold"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_cover"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/track_search_title"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_type_result"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Secondary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_type"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/track_search_title"
|
||||||
|
tools:text="Manga"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_start"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/track_start_date"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Bold"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_cover"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/track_search_type"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_start_result"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Secondary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_start"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/track_search_type"
|
||||||
|
tools:text="2018-10-01"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_status"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/track_status"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Bold"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_cover"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/track_search_start"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_status_result"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Secondary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_status"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/track_search_start"
|
||||||
|
tools:text="Ongoing"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/track_search_summary"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="7"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1.Secondary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/track_search_cover"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/track_search_status"
|
||||||
|
app:layout_constraintVertical_bias="0.333"
|
||||||
|
tools:text="This is the summary of the manga that fits This is the summary of the manga that fits This is the summary of the manga that fits This is the summary of the manga that fits This is the summary of the manga that fits This is the summary of the manga that fits This is the summary of the manga that fits "/>
|
||||||
|
|
||||||
|
<android.support.constraint.Guideline
|
||||||
|
android:id="@+id/guideline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintGuide_begin="150dp"/>
|
||||||
|
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
</android.support.v7.widget.CardView>
|
|
@ -378,7 +378,7 @@
|
||||||
<string name="download_unread">Download unread</string>
|
<string name="download_unread">Download unread</string>
|
||||||
<string name="confirm_delete_chapters">Are you sure you want to delete selected chapters?</string>
|
<string name="confirm_delete_chapters">Are you sure you want to delete selected chapters?</string>
|
||||||
|
|
||||||
<!-- MyAnimeList fragment -->
|
<!-- Tracking Screen -->
|
||||||
<string name="manga_tracking_tab">Tracking</string>
|
<string name="manga_tracking_tab">Tracking</string>
|
||||||
<string name="reading">Reading</string>
|
<string name="reading">Reading</string>
|
||||||
<string name="completed">Completed</string>
|
<string name="completed">Completed</string>
|
||||||
|
@ -388,6 +388,11 @@
|
||||||
<string name="score">Score</string>
|
<string name="score">Score</string>
|
||||||
<string name="title">Title</string>
|
<string name="title">Title</string>
|
||||||
<string name="status">Status</string>
|
<string name="status">Status</string>
|
||||||
|
<string name="track_status">Status</string>
|
||||||
|
<string name="track_start_date">Started</string>
|
||||||
|
<string name="track_type">Type</string>
|
||||||
|
<string name="track_author">Author</string>
|
||||||
|
<string name="url_not_set">Manga url is not set please click title and select manga again</string>
|
||||||
|
|
||||||
<!-- Category activity -->
|
<!-- Category activity -->
|
||||||
<string name="error_category_exists">A category with this name already exists!</string>
|
<string name="error_category_exists">A category with this name already exists!</string>
|
||||||
|
|
Reference in a new issue