mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-19 03:59:19 +01:00
Added recently read tab (#316)
This commit is contained in:
parent
11262f86f9
commit
7ba898f701
@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.data.database.queries.*
|
|||||||
* This class provides operations to manage the database through its interfaces.
|
* This class provides operations to manage the database through its interfaces.
|
||||||
*/
|
*/
|
||||||
open class DatabaseHelper(context: Context)
|
open class DatabaseHelper(context: Context)
|
||||||
: MangaQueries, ChapterQueries, MangaSyncQueries, CategoryQueries, MangaCategoryQueries {
|
: MangaQueries, ChapterQueries, MangaSyncQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries {
|
||||||
|
|
||||||
override val db = DefaultStorIOSQLite.builder()
|
override val db = DefaultStorIOSQLite.builder()
|
||||||
.sqliteOpenHelper(DbOpenHelper(context))
|
.sqliteOpenHelper(DbOpenHelper(context))
|
||||||
@ -18,6 +18,7 @@ open class DatabaseHelper(context: Context)
|
|||||||
.addTypeMapping(MangaSync::class.java, MangaSyncSQLiteTypeMapping())
|
.addTypeMapping(MangaSync::class.java, MangaSyncSQLiteTypeMapping())
|
||||||
.addTypeMapping(Category::class.java, CategorySQLiteTypeMapping())
|
.addTypeMapping(Category::class.java, CategorySQLiteTypeMapping())
|
||||||
.addTypeMapping(MangaCategory::class.java, MangaCategorySQLiteTypeMapping())
|
.addTypeMapping(MangaCategory::class.java, MangaCategorySQLiteTypeMapping())
|
||||||
|
.addTypeMapping(History::class.java, HistorySQLiteTypeMapping())
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)
|
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)
|
||||||
|
@ -17,7 +17,7 @@ class DbOpenHelper(context: Context)
|
|||||||
/**
|
/**
|
||||||
* Version of the database.
|
* Version of the database.
|
||||||
*/
|
*/
|
||||||
const val DATABASE_VERSION = 2
|
const val DATABASE_VERSION = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(db: SQLiteDatabase) = with(db) {
|
override fun onCreate(db: SQLiteDatabase) = with(db) {
|
||||||
@ -26,11 +26,13 @@ class DbOpenHelper(context: Context)
|
|||||||
execSQL(MangaSyncTable.createTableQuery)
|
execSQL(MangaSyncTable.createTableQuery)
|
||||||
execSQL(CategoryTable.createTableQuery)
|
execSQL(CategoryTable.createTableQuery)
|
||||||
execSQL(MangaCategoryTable.createTableQuery)
|
execSQL(MangaCategoryTable.createTableQuery)
|
||||||
|
execSQL(HistoryTable.createTableQuery)
|
||||||
|
|
||||||
// DB indexes
|
// DB indexes
|
||||||
execSQL(MangaTable.createUrlIndexQuery)
|
execSQL(MangaTable.createUrlIndexQuery)
|
||||||
execSQL(MangaTable.createFavoriteIndexQuery)
|
execSQL(MangaTable.createFavoriteIndexQuery)
|
||||||
execSQL(ChapterTable.createMangaIdIndexQuery)
|
execSQL(ChapterTable.createMangaIdIndexQuery)
|
||||||
|
execSQL(HistoryTable.createChapterIdIndexQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||||
@ -41,6 +43,11 @@ class DbOpenHelper(context: Context)
|
|||||||
db.execSQL("""UPDATE mangas SET thumbnail_url =
|
db.execSQL("""UPDATE mangas SET thumbnail_url =
|
||||||
REPLACE(thumbnail_url, '93.174.95.110', 'kissmanga.com') WHERE source = 4""")
|
REPLACE(thumbnail_url, '93.174.95.110', 'kissmanga.com') WHERE source = 4""")
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 3) {
|
||||||
|
// Initialize history tables
|
||||||
|
db.execSQL(HistoryTable.createTableQuery)
|
||||||
|
db.execSQL(HistoryTable.createChapterIdIndexQuery)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigure(db: SQLiteDatabase) {
|
override fun onConfigure(db: SQLiteDatabase) {
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.database.models;
|
||||||
|
|
||||||
|
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteColumn;
|
||||||
|
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteType;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing the history statistics of a chapter
|
||||||
|
*/
|
||||||
|
@StorIOSQLiteType(table = HistoryTable.TABLE)
|
||||||
|
public class History implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id of history object.
|
||||||
|
*/
|
||||||
|
@StorIOSQLiteColumn(name = HistoryTable.COL_ID, key = true)
|
||||||
|
public Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chapter id of history object.
|
||||||
|
*/
|
||||||
|
@StorIOSQLiteColumn(name = HistoryTable.COL_CHAPTER_ID)
|
||||||
|
public long chapter_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last time chapter was read in time long format
|
||||||
|
*/
|
||||||
|
@StorIOSQLiteColumn(name = HistoryTable.COL_LAST_READ)
|
||||||
|
public long last_read;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total time chapter was read - todo not yet implemented
|
||||||
|
*/
|
||||||
|
@StorIOSQLiteColumn(name = HistoryTable.COL_TIME_READ)
|
||||||
|
public long time_read;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty history constructor
|
||||||
|
*/
|
||||||
|
public History() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* History constructor
|
||||||
|
*
|
||||||
|
* @param chapter chapter object
|
||||||
|
* @return history object
|
||||||
|
*/
|
||||||
|
public static History create(Chapter chapter) {
|
||||||
|
History history = new History();
|
||||||
|
history.chapter_id = chapter.id;
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.database.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing manga, chapter and history
|
||||||
|
*/
|
||||||
|
public class MangaChapterHistory {
|
||||||
|
/**
|
||||||
|
* Object containing manga and chapter
|
||||||
|
*/
|
||||||
|
public MangaChapter mangaChapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing history
|
||||||
|
*/
|
||||||
|
public History history;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MangaChapterHistory constructor
|
||||||
|
*
|
||||||
|
* @param mangaChapter object containing manga and chapter
|
||||||
|
* @param history object containing history
|
||||||
|
*/
|
||||||
|
public MangaChapterHistory(MangaChapter mangaChapter, History history) {
|
||||||
|
this.mangaChapter = mangaChapter;
|
||||||
|
this.history = history;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.database.queries
|
||||||
|
|
||||||
|
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
||||||
|
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
|
import eu.kanade.tachiyomi.data.database.resolvers.HistoryLastReadPutResolver
|
||||||
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
interface HistoryQueries : DbProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert history into database
|
||||||
|
* @param history object containing history information
|
||||||
|
*/
|
||||||
|
fun insertHistory(history: History) = db.put().`object`(history).prepare()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns history of recent manga containing last read chapter
|
||||||
|
* @param date recent date range
|
||||||
|
*/
|
||||||
|
fun getRecentManga(date: Date) = db.get()
|
||||||
|
.listOfObjects(MangaChapterHistory::class.java)
|
||||||
|
.withQuery(RawQuery.builder()
|
||||||
|
.query(getRecentMangasQuery())
|
||||||
|
.args(date.time)
|
||||||
|
.observesTables(HistoryTable.TABLE)
|
||||||
|
.build())
|
||||||
|
.withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
||||||
|
.prepare()
|
||||||
|
|
||||||
|
fun getHistoryByMangaId(mangaId: Long) = db.get()
|
||||||
|
.listOfObjects(History::class.java)
|
||||||
|
.withQuery(RawQuery.builder()
|
||||||
|
.query(getHistoryByMangaId())
|
||||||
|
.args(mangaId)
|
||||||
|
.observesTables(HistoryTable.TABLE)
|
||||||
|
.build())
|
||||||
|
.prepare()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the history last read.
|
||||||
|
* Inserts history object if not yet in database
|
||||||
|
* @param history history object
|
||||||
|
*/
|
||||||
|
fun updateHistoryLastRead(history: History) = db.put()
|
||||||
|
.`object`(history)
|
||||||
|
.withPutResolver(HistoryLastReadPutResolver())
|
||||||
|
.prepare()
|
||||||
|
}
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.database.queries
|
|||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable as Category
|
import eu.kanade.tachiyomi.data.database.tables.CategoryTable as Category
|
||||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable as History
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
|
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
|
||||||
|
|
||||||
@ -39,6 +40,38 @@ fun getRecentsQuery() = """
|
|||||||
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
|
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query to get the recently read chapters of manga from the library up to a date.
|
||||||
|
* The max_last_read table contains the most recent chapters grouped by manga
|
||||||
|
* The select statement returns all information of chapters that have the same id as the chapter in max_last_read
|
||||||
|
* and are read after the given time period
|
||||||
|
* @return return limit is 25
|
||||||
|
*/
|
||||||
|
fun getRecentMangasQuery() = """
|
||||||
|
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
|
||||||
|
FROM ${Manga.TABLE}
|
||||||
|
JOIN ${Chapter.TABLE}
|
||||||
|
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
|
||||||
|
JOIN ${History.TABLE}
|
||||||
|
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
||||||
|
JOIN (
|
||||||
|
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID}, MAX(${History.TABLE}.${History.COL_LAST_READ}) as ${History.COL_LAST_READ}
|
||||||
|
FROM ${Chapter.TABLE} JOIN ${History.TABLE}
|
||||||
|
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
||||||
|
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS max_last_read
|
||||||
|
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
|
||||||
|
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ? AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
||||||
|
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
|
||||||
|
LIMIT 25
|
||||||
|
"""
|
||||||
|
|
||||||
|
fun getHistoryByMangaId() = """
|
||||||
|
SELECT ${History.TABLE}.*
|
||||||
|
FROM ${History.TABLE}
|
||||||
|
JOIN ${Chapter.TABLE}
|
||||||
|
ON ${History.TABLE}.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID}
|
||||||
|
WHERE ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = ? AND ${History.TABLE}.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID}
|
||||||
|
"""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query to get the categories for a manga.
|
* Query to get the categories for a manga.
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.database.resolvers
|
||||||
|
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.support.annotation.NonNull
|
||||||
|
import com.pushtorefresh.storio.sqlite.StorIOSQLite
|
||||||
|
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
|
||||||
|
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
|
||||||
|
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
||||||
|
import eu.kanade.tachiyomi.data.database.inTransactionReturn
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
||||||
|
|
||||||
|
class HistoryLastReadPutResolver : PutResolver<History>() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates last_read time of chapter
|
||||||
|
*/
|
||||||
|
override fun performPut(@NonNull db: StorIOSQLite, @NonNull history: History): PutResult = db.inTransactionReturn {
|
||||||
|
// Create put query
|
||||||
|
val updateQuery = mapToUpdateQuery(history)
|
||||||
|
val contentValues = mapToContentValues(history)
|
||||||
|
|
||||||
|
// Execute query
|
||||||
|
val numberOfRowsUpdated = db.internal().update(updateQuery, contentValues)
|
||||||
|
|
||||||
|
// If chapter not found in history insert into database
|
||||||
|
if (numberOfRowsUpdated == 0) {
|
||||||
|
db.put().`object`(history).prepare().asRxObservable().subscribe()
|
||||||
|
}
|
||||||
|
// Update result
|
||||||
|
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates update query
|
||||||
|
* @param history object
|
||||||
|
*/
|
||||||
|
fun mapToUpdateQuery(history: History) = UpdateQuery.builder()
|
||||||
|
.table(HistoryTable.TABLE)
|
||||||
|
.where("${HistoryTable.COL_CHAPTER_ID} = ?")
|
||||||
|
.whereArgs(history.chapter_id)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create content query
|
||||||
|
* @param history object
|
||||||
|
*/
|
||||||
|
fun mapToContentValues(history: History) = ContentValues(1).apply {
|
||||||
|
put(HistoryTable.COL_LAST_READ, history.last_read)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,7 +20,7 @@ class MangaChapterGetResolver : DefaultGetResolver<MangaChapter>() {
|
|||||||
val manga = mangaGetResolver.mapFromCursor(cursor)
|
val manga = mangaGetResolver.mapFromCursor(cursor)
|
||||||
val chapter = chapterGetResolver.mapFromCursor(cursor)
|
val chapter = chapterGetResolver.mapFromCursor(cursor)
|
||||||
manga.id = chapter.manga_id
|
manga.id = chapter.manga_id
|
||||||
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"));
|
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
|
||||||
|
|
||||||
return MangaChapter(manga, chapter)
|
return MangaChapter(manga, chapter)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.database.resolvers
|
||||||
|
|
||||||
|
import android.database.Cursor
|
||||||
|
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.*
|
||||||
|
|
||||||
|
class MangaChapterHistoryGetResolver : DefaultGetResolver<MangaChapterHistory>() {
|
||||||
|
companion object {
|
||||||
|
val INSTANCE = MangaChapterHistoryGetResolver()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manga get resolver
|
||||||
|
*/
|
||||||
|
private val mangaGetResolver = MangaStorIOSQLiteGetResolver()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chapter get resolver
|
||||||
|
*/
|
||||||
|
private val chapterResolver = ChapterStorIOSQLiteGetResolver()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* History get resolver
|
||||||
|
*/
|
||||||
|
private val historyGetResolver = HistoryStorIOSQLiteGetResolver()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map correct objects from cursor result
|
||||||
|
*/
|
||||||
|
override fun mapFromCursor(cursor: Cursor): MangaChapterHistory {
|
||||||
|
// Get manga object
|
||||||
|
val manga = mangaGetResolver.mapFromCursor(cursor)
|
||||||
|
|
||||||
|
// Get chapter object
|
||||||
|
val chapter = chapterResolver.mapFromCursor(cursor)
|
||||||
|
|
||||||
|
// Get history object
|
||||||
|
val history = historyGetResolver.mapFromCursor(cursor)
|
||||||
|
|
||||||
|
// Make certain column conflicts are dealt with
|
||||||
|
manga.id = chapter.manga_id
|
||||||
|
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
|
||||||
|
chapter.id = history.chapter_id
|
||||||
|
|
||||||
|
// Create mangaChapter object
|
||||||
|
val mangaChapter = MangaChapter(manga, chapter)
|
||||||
|
|
||||||
|
// Return result
|
||||||
|
return MangaChapterHistory(mangaChapter, history)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.database.tables
|
||||||
|
|
||||||
|
object HistoryTable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table name
|
||||||
|
*/
|
||||||
|
const val TABLE = "history"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id column name
|
||||||
|
*/
|
||||||
|
const val COL_ID = "${TABLE}_id"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chapter id column name
|
||||||
|
*/
|
||||||
|
const val COL_CHAPTER_ID = "${TABLE}_chapter_id"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last read column name
|
||||||
|
*/
|
||||||
|
const val COL_LAST_READ = "${TABLE}_last_read"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time read column name
|
||||||
|
*/
|
||||||
|
const val COL_TIME_READ = "${TABLE}_time_read"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* query to create history table
|
||||||
|
*/
|
||||||
|
val createTableQuery: String
|
||||||
|
get() = """CREATE TABLE $TABLE(
|
||||||
|
$COL_ID INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
$COL_CHAPTER_ID INTEGER NOT NULL UNIQUE,
|
||||||
|
$COL_LAST_READ LONG,
|
||||||
|
$COL_TIME_READ LONG,
|
||||||
|
FOREIGN KEY($COL_CHAPTER_ID) REFERENCES ${ChapterTable.TABLE} (${ChapterTable.COL_ID})
|
||||||
|
ON DELETE CASCADE
|
||||||
|
)"""
|
||||||
|
|
||||||
|
/**
|
||||||
|
* query to index history chapter id
|
||||||
|
*/
|
||||||
|
val createChapterIdIndexQuery: String
|
||||||
|
get() = "CREATE INDEX ${TABLE}_${COL_CHAPTER_ID}_index ON $TABLE($COL_CHAPTER_ID)"
|
||||||
|
}
|
@ -24,7 +24,8 @@ import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersPresenter
|
|||||||
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoPresenter
|
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoPresenter
|
||||||
import eu.kanade.tachiyomi.ui.manga.myanimelist.MyAnimeListPresenter
|
import eu.kanade.tachiyomi.ui.manga.myanimelist.MyAnimeListPresenter
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter
|
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter
|
||||||
import eu.kanade.tachiyomi.ui.recent.RecentChaptersPresenter
|
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersPresenter
|
||||||
|
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadPresenter
|
||||||
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
|
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ interface AppComponent {
|
|||||||
fun inject(myAnimeListPresenter: MyAnimeListPresenter)
|
fun inject(myAnimeListPresenter: MyAnimeListPresenter)
|
||||||
fun inject(categoryPresenter: CategoryPresenter)
|
fun inject(categoryPresenter: CategoryPresenter)
|
||||||
fun inject(recentChaptersPresenter: RecentChaptersPresenter)
|
fun inject(recentChaptersPresenter: RecentChaptersPresenter)
|
||||||
|
fun inject(recentlyReadPresenter: RecentlyReadPresenter)
|
||||||
fun inject(backupPresenter: BackupPresenter)
|
fun inject(backupPresenter: BackupPresenter)
|
||||||
|
|
||||||
fun inject(mainActivity: MainActivity)
|
fun inject(mainActivity: MainActivity)
|
||||||
|
@ -13,7 +13,8 @@ import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
|||||||
import eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment
|
import eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment
|
||||||
import eu.kanade.tachiyomi.ui.download.DownloadFragment
|
import eu.kanade.tachiyomi.ui.download.DownloadFragment
|
||||||
import eu.kanade.tachiyomi.ui.library.LibraryFragment
|
import eu.kanade.tachiyomi.ui.library.LibraryFragment
|
||||||
import eu.kanade.tachiyomi.ui.recent.RecentChaptersFragment
|
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersFragment
|
||||||
|
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadFragment
|
||||||
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
|
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.android.synthetic.main.toolbar.*
|
import kotlinx.android.synthetic.main.toolbar.*
|
||||||
@ -50,6 +51,7 @@ class MainActivity : BaseActivity() {
|
|||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_drawer_library -> setFragment(LibraryFragment.newInstance())
|
R.id.nav_drawer_library -> setFragment(LibraryFragment.newInstance())
|
||||||
R.id.nav_drawer_recent_updates -> setFragment(RecentChaptersFragment.newInstance())
|
R.id.nav_drawer_recent_updates -> setFragment(RecentChaptersFragment.newInstance())
|
||||||
|
R.id.nav_drawer_recent_manga -> setFragment(RecentlyReadFragment.newInstance())
|
||||||
R.id.nav_drawer_catalogues -> setFragment(CatalogueFragment.newInstance())
|
R.id.nav_drawer_catalogues -> setFragment(CatalogueFragment.newInstance())
|
||||||
R.id.nav_drawer_downloads -> setFragment(DownloadFragment.newInstance())
|
R.id.nav_drawer_downloads -> setFragment(DownloadFragment.newInstance())
|
||||||
R.id.nav_drawer_settings -> startActivity(Intent(this, SettingsActivity::class.java))
|
R.id.nav_drawer_settings -> startActivity(Intent(this, SettingsActivity::class.java))
|
||||||
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
|||||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaSync
|
import eu.kanade.tachiyomi.data.database.models.MangaSync
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
@ -24,6 +25,7 @@ import rx.schedulers.Schedulers
|
|||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||||
@ -289,6 +291,7 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check whether the given chapter is downloaded
|
// Check whether the given chapter is downloaded
|
||||||
fun isChapterDownloaded(chapter: Chapter): Boolean {
|
fun isChapterDownloaded(chapter: Chapter): Boolean {
|
||||||
return downloadManager.isChapterDownloaded(source, manga, chapter)
|
return downloadManager.isChapterDownloaded(source, manga, chapter)
|
||||||
@ -340,6 +343,12 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.updateChapterProgress(chapter).asRxObservable().subscribe()
|
db.updateChapterProgress(chapter).asRxObservable().subscribe()
|
||||||
|
// Update last read data
|
||||||
|
db.updateHistoryLastRead(History.create(chapter)
|
||||||
|
.apply { last_read = Date().time })
|
||||||
|
.asRxObservable()
|
||||||
|
.doOnError { Timber.e(it.message) }
|
||||||
|
.subscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.ui.recent
|
package eu.kanade.tachiyomi.ui.recent_updates
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -72,7 +72,7 @@ class RecentChaptersAdapter(val fragment: RecentChaptersFragment) : FlexibleAdap
|
|||||||
// Check which view type and set correct values.
|
// Check which view type and set correct values.
|
||||||
when (viewType) {
|
when (viewType) {
|
||||||
VIEW_TYPE_CHAPTER -> {
|
VIEW_TYPE_CHAPTER -> {
|
||||||
view = parent.inflate(R.layout.item_recent_chapter)
|
view = parent.inflate(R.layout.item_recent_chapters)
|
||||||
return RecentChaptersHolder(view, this, fragment)
|
return RecentChaptersHolder(view, this, fragment)
|
||||||
}
|
}
|
||||||
VIEW_TYPE_SECTION -> {
|
VIEW_TYPE_SECTION -> {
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.ui.recent
|
package eu.kanade.tachiyomi.ui.recent_updates
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.DialogFragment
|
import android.support.v4.app.DialogFragment
|
||||||
@ -213,7 +213,7 @@ class RecentChaptersFragment : BaseRxFragment<RecentChaptersPresenter>(), Action
|
|||||||
*/
|
*/
|
||||||
fun onNextMangaChapters(chapters: List<Any>) {
|
fun onNextMangaChapters(chapters: List<Any>) {
|
||||||
(activity as MainActivity).updateEmptyView(chapters.isEmpty(),
|
(activity as MainActivity).updateEmptyView(chapters.isEmpty(),
|
||||||
R.string.information_no_recent, R.drawable.ic_history_black_128dp)
|
R.string.information_no_recent, R.drawable.ic_update_black_128dp)
|
||||||
|
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
adapter.setItems(chapters)
|
adapter.setItems(chapters)
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.ui.recent
|
package eu.kanade.tachiyomi.ui.recent_updates
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
@ -7,11 +7,11 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapter
|
|||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
|
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.util.getResourceColor
|
import eu.kanade.tachiyomi.util.getResourceColor
|
||||||
import kotlinx.android.synthetic.main.item_recent_chapter.view.*
|
import kotlinx.android.synthetic.main.item_recent_chapters.view.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holder that contains chapter item
|
* Holder that contains chapter item
|
||||||
* Uses R.layout.item_recent_chapter.
|
* Uses R.layout.item_recent_chapters.
|
||||||
* UI related actions should be called from here.
|
* UI related actions should be called from here.
|
||||||
*
|
*
|
||||||
* @param view the inflated view for this holder.
|
* @param view the inflated view for this holder.
|
||||||
@ -19,7 +19,7 @@ import kotlinx.android.synthetic.main.item_recent_chapter.view.*
|
|||||||
* @param listener a listener to react to single tap and long tap events.
|
* @param listener a listener to react to single tap and long tap events.
|
||||||
* @constructor creates a new recent chapter holder.
|
* @constructor creates a new recent chapter holder.
|
||||||
*/
|
*/
|
||||||
class RecentChaptersHolder(view: View, private val adapter: RecentChaptersAdapter, listener: FlexibleViewHolder.OnListItemClickListener) :
|
class RecentChaptersHolder(view: View, private val adapter: RecentChaptersAdapter, listener: OnListItemClickListener) :
|
||||||
FlexibleViewHolder(view, adapter, listener) {
|
FlexibleViewHolder(view, adapter, listener) {
|
||||||
/**
|
/**
|
||||||
* Color of read chapter
|
* Color of read chapter
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.ui.recent
|
package eu.kanade.tachiyomi.ui.recent_updates
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.ui.recent
|
package eu.kanade.tachiyomi.ui.recent_updates
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
@ -0,0 +1,52 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.recently_read
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
|
import eu.kanade.tachiyomi.util.inflate
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter of RecentlyReadHolder.
|
||||||
|
* Connection between Fragment and Holder
|
||||||
|
* Holder updates should be called from here.
|
||||||
|
*
|
||||||
|
* @param fragment a RecentlyReadFragment object
|
||||||
|
* @constructor creates an instance of the adapter.
|
||||||
|
*/
|
||||||
|
class RecentlyReadAdapter(val fragment: RecentlyReadFragment) : FlexibleAdapter<RecyclerView.ViewHolder, Any>() {
|
||||||
|
/**
|
||||||
|
* Called when ViewHolder is created
|
||||||
|
* @param parent parent View
|
||||||
|
* @param viewType int containing viewType
|
||||||
|
*/
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder? {
|
||||||
|
val view = parent.inflate(R.layout.item_recent_manga)
|
||||||
|
return RecentlyReadHolder(view, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when ViewHolder is bind
|
||||||
|
* @param holder bind holder
|
||||||
|
* @param position position of holder
|
||||||
|
*/
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
|
||||||
|
val item = getItem(position) as MangaChapterHistory
|
||||||
|
(holder as RecentlyReadHolder).onSetValues(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update items
|
||||||
|
* @param items items
|
||||||
|
*/
|
||||||
|
fun setItems(items: List<MangaChapterHistory>) {
|
||||||
|
mItems = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDataSet(param: String?) {
|
||||||
|
// Empty function
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.recently_read
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
|
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
|
||||||
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.MangaActivity
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
|
import eu.kanade.tachiyomi.widget.NpaLinearLayoutManager
|
||||||
|
import kotlinx.android.synthetic.main.fragment_recent_manga.*
|
||||||
|
import nucleus.factory.RequiresPresenter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment that shows recently read manga.
|
||||||
|
* Uses R.layout.fragment_recent_manga.
|
||||||
|
* UI related actions should be called from here.
|
||||||
|
*/
|
||||||
|
@RequiresPresenter(RecentlyReadPresenter::class)
|
||||||
|
class RecentlyReadFragment : BaseRxFragment<RecentlyReadPresenter>() {
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Create new RecentChaptersFragment.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun newInstance(): RecentlyReadFragment {
|
||||||
|
return RecentlyReadFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter containing the recent manga.
|
||||||
|
*/
|
||||||
|
lateinit var adapter: RecentlyReadAdapter
|
||||||
|
private set
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when view gets created
|
||||||
|
*
|
||||||
|
* @param inflater layout inflater
|
||||||
|
* @param container view group
|
||||||
|
* @param savedState status of saved state
|
||||||
|
*/
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.fragment_recent_manga, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when view is created
|
||||||
|
*
|
||||||
|
* @param view created view
|
||||||
|
* @param savedInstanceState status of saved sate
|
||||||
|
*/
|
||||||
|
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
|
||||||
|
// Initialize adapter
|
||||||
|
recycler.layoutManager = NpaLinearLayoutManager(activity)
|
||||||
|
adapter = RecentlyReadAdapter(this)
|
||||||
|
recycler.setHasFixedSize(true)
|
||||||
|
recycler.adapter = adapter
|
||||||
|
|
||||||
|
// Update toolbar text
|
||||||
|
setToolbarTitle(R.string.label_recent_manga)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate adapter with chapters
|
||||||
|
*
|
||||||
|
* @param mangaHistory list of manga history
|
||||||
|
*/
|
||||||
|
fun onNextManga(mangaHistory: List<MangaChapterHistory>) {
|
||||||
|
(activity as MainActivity).updateEmptyView(mangaHistory.isEmpty(),
|
||||||
|
R.string.information_no_recent_manga, R.drawable.ic_glasses_black_128dp)
|
||||||
|
|
||||||
|
adapter.setItems(mangaHistory)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset last read of chapter to 0L
|
||||||
|
* @param history history belonging to chapter
|
||||||
|
*/
|
||||||
|
fun removeFromHistory(history: History) {
|
||||||
|
presenter.removeFromHistory(history)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all chapters belonging to manga from library
|
||||||
|
* @param mangaId id of manga
|
||||||
|
*/
|
||||||
|
fun removeAllFromHistory(mangaId: Long) {
|
||||||
|
presenter.removeAllFromHistory(mangaId)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open chapter to continue reading
|
||||||
|
* @param chapter chapter that is opened
|
||||||
|
* @param manga manga belonging to chapter
|
||||||
|
*/
|
||||||
|
fun openChapter(chapter: Chapter, manga: Manga) {
|
||||||
|
val intent = ReaderActivity.newIntent(activity, manga, chapter)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open manga info page
|
||||||
|
* @param manga manga belonging to info page
|
||||||
|
*/
|
||||||
|
fun openMangaInfo(manga: Manga) {
|
||||||
|
val intent = MangaActivity.newIntent(activity, manga, true)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the timestamp of last read
|
||||||
|
* @param history history containing time of last read
|
||||||
|
*/
|
||||||
|
fun getLastRead(history: History): String? {
|
||||||
|
return presenter.getLastRead(history)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.recently_read
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView
|
||||||
|
import android.view.View
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
|
import eu.kanade.tachiyomi.data.source.SourceManager
|
||||||
|
import kotlinx.android.synthetic.main.dialog_remove_recently.view.*
|
||||||
|
import kotlinx.android.synthetic.main.item_recent_manga.view.*
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
import java.text.DecimalFormatSymbols
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holder that contains recent manga item
|
||||||
|
* Uses R.layout.item_recent_manga.
|
||||||
|
* UI related actions should be called from here.
|
||||||
|
*
|
||||||
|
* @param view the inflated view for this holder.
|
||||||
|
* @param adapter the adapter handling this holder.
|
||||||
|
* @constructor creates a new recent chapter holder.
|
||||||
|
*/
|
||||||
|
class RecentlyReadHolder(view: View, private val adapter: RecentlyReadAdapter) :
|
||||||
|
RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DecimalFormat used to display correct chapter number
|
||||||
|
*/
|
||||||
|
private val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols().apply { decimalSeparator = '.' })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set values of view
|
||||||
|
*
|
||||||
|
* @param item item containing history information
|
||||||
|
*/
|
||||||
|
fun onSetValues(item: MangaChapterHistory) {
|
||||||
|
// Retrieve objects
|
||||||
|
val manga = item.mangaChapter.manga
|
||||||
|
val chapter = item.mangaChapter.chapter
|
||||||
|
val history = item.history
|
||||||
|
|
||||||
|
// Set manga title
|
||||||
|
itemView.manga_title.text = manga.title
|
||||||
|
|
||||||
|
// Set source + chapter title
|
||||||
|
val formattedNumber = decimalFormat.format(chapter.chapter_number.toDouble())
|
||||||
|
itemView.manga_source.text = itemView.context.getString(R.string.recent_manga_source)
|
||||||
|
.format(SourceManager(adapter.fragment.context).get(manga.source)?.name, formattedNumber)
|
||||||
|
|
||||||
|
// Set last read timestamp title
|
||||||
|
itemView.last_read.text = adapter.fragment.getLastRead(history)
|
||||||
|
|
||||||
|
// Set cover
|
||||||
|
if (!manga.thumbnail_url.isNullOrEmpty()) {
|
||||||
|
Glide.with(itemView.context)
|
||||||
|
.load(manga)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.RESULT)
|
||||||
|
.centerCrop()
|
||||||
|
.into(itemView.cover)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set remove clickListener
|
||||||
|
itemView.remove.setOnClickListener {
|
||||||
|
MaterialDialog.Builder(itemView.context)
|
||||||
|
.title(R.string.action_remove)
|
||||||
|
.customView(R.layout.dialog_remove_recently, true)
|
||||||
|
.positiveText(R.string.action_remove)
|
||||||
|
.negativeText(android.R.string.cancel)
|
||||||
|
.onPositive { materialDialog, dialogAction ->
|
||||||
|
// Check if user wants all chapters reset
|
||||||
|
if (materialDialog.customView?.removeAll?.isChecked as Boolean) {
|
||||||
|
adapter.fragment.removeAllFromHistory(manga.id)
|
||||||
|
} else {
|
||||||
|
adapter.fragment.removeFromHistory(history)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onNegative { materialDialog, dialogAction ->
|
||||||
|
materialDialog.dismiss()
|
||||||
|
}
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set continue reading clickListener
|
||||||
|
itemView.resume.setOnClickListener {
|
||||||
|
adapter.fragment.openChapter(chapter, manga)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set open manga info clickListener
|
||||||
|
itemView.cover.setOnClickListener {
|
||||||
|
adapter.fragment.openMangaInfo(manga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.recently_read
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
import rx.Observable
|
||||||
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
|
import rx.schedulers.Schedulers
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the restartable.
|
||||||
|
*/
|
||||||
|
const private val GET_RECENT_MANGA = 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Presenter of RecentlyReadFragment.
|
||||||
|
* Contains information and data for fragment.
|
||||||
|
* Observable updates should be called from here.
|
||||||
|
*/
|
||||||
|
class RecentlyReadPresenter : BasePresenter<RecentlyReadFragment>() {
|
||||||
|
/**
|
||||||
|
* Used to connect to database
|
||||||
|
*/
|
||||||
|
@Inject lateinit var db: DatabaseHelper
|
||||||
|
|
||||||
|
override fun onCreate(savedState: Bundle?) {
|
||||||
|
super.onCreate(savedState)
|
||||||
|
|
||||||
|
// Used to get recent manga
|
||||||
|
restartableLatestCache(GET_RECENT_MANGA,
|
||||||
|
{ getRecentMangaObservable() },
|
||||||
|
{ recentMangaFragment, manga ->
|
||||||
|
// Update adapter to show recent manga's
|
||||||
|
recentMangaFragment.onNextManga(manga)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (savedState == null) {
|
||||||
|
// Start fetching recent manga
|
||||||
|
start(GET_RECENT_MANGA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get recent manga observable
|
||||||
|
* @return list of history
|
||||||
|
*/
|
||||||
|
fun getRecentMangaObservable(): Observable<MutableList<MangaChapterHistory>> {
|
||||||
|
// Set date for recent manga
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.time = Date()
|
||||||
|
cal.add(Calendar.MONTH, -1)
|
||||||
|
|
||||||
|
return db.getRecentManga(cal.time).asRxObservable()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset last read of chapter to 0L
|
||||||
|
* @param history history belonging to chapter
|
||||||
|
*/
|
||||||
|
fun removeFromHistory(history: History) {
|
||||||
|
history.last_read = 0L
|
||||||
|
db.updateHistoryLastRead(history).asRxObservable()
|
||||||
|
.doOnError { Timber.e(it.message) }.subscribe()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all chapters belonging to manga from library
|
||||||
|
* @param mangaId id of manga
|
||||||
|
*/
|
||||||
|
fun removeAllFromHistory(mangaId: Long) {
|
||||||
|
db.getHistoryByMangaId(mangaId).asRxObservable()
|
||||||
|
.take(1)
|
||||||
|
.flatMapIterable { it }
|
||||||
|
.doOnError { Timber.e(it.message) }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ result -> removeFromHistory(result) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the timestamp of last read
|
||||||
|
* @param history history containing time of last read
|
||||||
|
*/
|
||||||
|
fun getLastRead(history: History): String? {
|
||||||
|
return SimpleDateFormat("dd-MM-yyyy HH:mm",
|
||||||
|
Locale.getDefault()).format(Date(history.last_read))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
app/src/main/res/drawable/ic_glasses_black_128dp.xml
Normal file
9
app/src/main/res/drawable/ic_glasses_black_128dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="128dp"
|
||||||
|
android:height="128dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M3,10C2.76,10 2.55,10.09 2.41,10.25C2.27,10.4 2.21,10.62 2.24,10.86L2.74,13.85C2.82,14.5 3.4,15 4,15H7C7.64,15 8.36,14.44 8.5,13.82L9.56,10.63C9.6,10.5 9.57,10.31 9.5,10.19C9.39,10.07 9.22,10 9,10H3M7,17H4C2.38,17 0.96,15.74 0.76,14.14L0.26,11.15C0.15,10.3 0.39,9.5 0.91,8.92C1.43,8.34 2.19,8 3,8H9C9.83,8 10.58,8.35 11.06,8.96C11.17,9.11 11.27,9.27 11.35,9.45C11.78,9.36 12.22,9.36 12.64,9.45C12.72,9.27 12.82,9.11 12.94,8.96C13.41,8.35 14.16,8 15,8H21C21.81,8 22.57,8.34 23.09,8.92C23.6,9.5 23.84,10.3 23.74,11.11L23.23,14.18C23.04,15.74 21.61,17 20,17H17C15.44,17 13.92,15.81 13.54,14.3L12.64,11.59C12.26,11.31 11.73,11.31 11.35,11.59L10.43,14.37C10.07,15.82 8.56,17 7,17M15,10C14.78,10 14.61,10.07 14.5,10.19C14.42,10.31 14.4,10.5 14.45,10.7L15.46,13.75C15.64,14.44 16.36,15 17,15H20C20.59,15 21.18,14.5 21.25,13.89L21.76,10.82C21.79,10.62 21.73,10.4 21.59,10.25C21.45,10.09 21.24,10 21,10H15Z"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_glasses_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_glasses_black_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M3,10C2.76,10 2.55,10.09 2.41,10.25C2.27,10.4 2.21,10.62 2.24,10.86L2.74,13.85C2.82,14.5 3.4,15 4,15H7C7.64,15 8.36,14.44 8.5,13.82L9.56,10.63C9.6,10.5 9.57,10.31 9.5,10.19C9.39,10.07 9.22,10 9,10H3M7,17H4C2.38,17 0.96,15.74 0.76,14.14L0.26,11.15C0.15,10.3 0.39,9.5 0.91,8.92C1.43,8.34 2.19,8 3,8H9C9.83,8 10.58,8.35 11.06,8.96C11.17,9.11 11.27,9.27 11.35,9.45C11.78,9.36 12.22,9.36 12.64,9.45C12.72,9.27 12.82,9.11 12.94,8.96C13.41,8.35 14.16,8 15,8H21C21.81,8 22.57,8.34 23.09,8.92C23.6,9.5 23.84,10.3 23.74,11.11L23.23,14.18C23.04,15.74 21.61,17 20,17H17C15.44,17 13.92,15.81 13.54,14.3L12.64,11.59C12.26,11.31 11.73,11.31 11.35,11.59L10.43,14.37C10.07,15.82 8.56,17 7,17M15,10C14.78,10 14.61,10.07 14.5,10.19C14.42,10.31 14.4,10.5 14.45,10.7L15.46,13.75C15.64,14.44 16.36,15 17,15H20C20.59,15 21.18,14.5 21.25,13.89L21.76,10.82C21.79,10.62 21.73,10.4 21.59,10.25C21.45,10.09 21.24,10 21,10H15Z"/>
|
||||||
|
</vector>
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="128dp"
|
|
||||||
android:height="128dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
|
|
||||||
</vector>
|
|
9
app/src/main/res/drawable/ic_update_black_128dp.xml
Normal file
9
app/src/main/res/drawable/ic_update_black_128dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="128dp"
|
||||||
|
android:height="128dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M21,10.12h-6.78l2.74,-2.82c-2.73,-2.7 -7.15,-2.8 -9.88,-0.1 -2.73,2.71 -2.73,7.08 0,9.79 2.73,2.71 7.15,2.71 9.88,0C18.32,15.65 19,14.08 19,12.1h2c0,1.98 -0.88,4.55 -2.64,6.29 -3.51,3.48 -9.21,3.48 -12.72,0 -3.5,-3.47 -3.53,-9.11 -0.02,-12.58 3.51,-3.47 9.14,-3.47 12.65,0L21,3v7.12zM12.5,8v4.25l3.5,2.08 -0.72,1.21L11,13V8h1.5z"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_update_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_update_black_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M21,10.12h-6.78l2.74,-2.82c-2.73,-2.7 -7.15,-2.8 -9.88,-0.1 -2.73,2.71 -2.73,7.08 0,9.79 2.73,2.71 7.15,2.71 9.88,0C18.32,15.65 19,14.08 19,12.1h2c0,1.98 -0.88,4.55 -2.64,6.29 -3.51,3.48 -9.21,3.48 -12.72,0 -3.5,-3.47 -3.53,-9.11 -0.02,-12.58 3.51,-3.47 9.14,-3.47 12.65,0L21,3v7.12zM12.5,8v4.25l3.5,2.08 -0.72,1.21L11,13V8h1.5z"/>
|
||||||
|
</vector>
|
22
app/src/main/res/layout/dialog_remove_recently.xml
Normal file
22
app/src/main/res/layout/dialog_remove_recently.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/activity_vertical_margin">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/dialog_remove_recently_description"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Body1"/>
|
||||||
|
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/removeAll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="18dp"
|
||||||
|
android:text="@string/dialog_remove_recently_reset"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -10,6 +10,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:descendantFocusability="blocksDescendants"
|
android:descendantFocusability="blocksDescendants"
|
||||||
tools:listitem="@layout/item_recent_chapter"/>
|
tools:listitem="@layout/item_recent_chapters">
|
||||||
|
|
||||||
|
</android.support.v7.widget.RecyclerView>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
16
app/src/main/res/layout/fragment_recent_manga.xml
Normal file
16
app/src/main/res/layout/fragment_recent_manga.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:listitem="@layout/item_recent_manga">
|
||||||
|
|
||||||
|
</android.support.v7.widget.RecyclerView>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
82
app/src/main/res/layout/item_recent_manga.xml
Normal file
82
app/src/main/res/layout/item_recent_manga.xml
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.v7.widget.CardView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/cv_manga"
|
||||||
|
style="@style/Theme.Widget.CardView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/cover"
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="@string/description_cover"
|
||||||
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/card_margin">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/manga_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.Title"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/manga_source"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/manga_title"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.Body2"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/last_read"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/manga_source"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.Body2.Hint"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/remove"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="?attr/selectable_list_drawable"
|
||||||
|
android:clickable="true"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:text="@string/action_remove"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.Button.Negative"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/resume"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_toEndOf="@id/remove"
|
||||||
|
android:layout_toRightOf="@id/remove"
|
||||||
|
android:background="?attr/selectable_list_drawable"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:text="@string/action_resume"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.Button"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</android.support.v7.widget.CardView>
|
@ -7,10 +7,15 @@
|
|||||||
android:id="@+id/nav_drawer_library"
|
android:id="@+id/nav_drawer_library"
|
||||||
android:icon="@drawable/ic_book_black_24dp"
|
android:icon="@drawable/ic_book_black_24dp"
|
||||||
android:title="@string/label_library" />
|
android:title="@string/label_library" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_drawer_recent_manga"
|
||||||
|
android:icon="@drawable/ic_glasses_black_24dp"
|
||||||
|
android:title="@string/label_recent_manga"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_drawer_recent_updates"
|
android:id="@+id/nav_drawer_recent_updates"
|
||||||
android:icon="@drawable/ic_history_black_24dp"
|
android:icon="@drawable/ic_update_black_24dp"
|
||||||
android:title="@string/label_recent_updates" />
|
android:title="@string/label_recent_updates" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_drawer_catalogues"
|
android:id="@+id/nav_drawer_catalogues"
|
||||||
android:icon="@drawable/ic_explore_black_24dp"
|
android:icon="@drawable/ic_explore_black_24dp"
|
||||||
|
@ -136,4 +136,12 @@
|
|||||||
<item>ac</item>
|
<item>ac</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="remove_recently_read">
|
||||||
|
<item>@string/scale_type_fit_screen</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="remove_recently_read_values">
|
||||||
|
<item>remove</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -70,4 +70,6 @@
|
|||||||
|
|
||||||
<color name="md_blue_grey_900">#263238</color>
|
<color name="md_blue_grey_900">#263238</color>
|
||||||
|
|
||||||
|
<color name="md_red_500">#F44336</color>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -7,6 +7,7 @@
|
|||||||
<string name="label_settings">Settings</string>
|
<string name="label_settings">Settings</string>
|
||||||
<string name="label_download_queue">Download queue</string>
|
<string name="label_download_queue">Download queue</string>
|
||||||
<string name="label_library">My library</string>
|
<string name="label_library">My library</string>
|
||||||
|
<string name="label_recent_manga">Recently read</string>
|
||||||
<string name="label_recent_updates">Recent updates</string>
|
<string name="label_recent_updates">Recent updates</string>
|
||||||
<string name="label_catalogues">Catalogues</string>
|
<string name="label_catalogues">Catalogues</string>
|
||||||
<string name="label_categories">Categories</string>
|
<string name="label_categories">Categories</string>
|
||||||
@ -46,6 +47,8 @@
|
|||||||
<string name="action_previous_chapter">Previous chapter</string>
|
<string name="action_previous_chapter">Previous chapter</string>
|
||||||
<string name="action_next_chapter">Next chapter</string>
|
<string name="action_next_chapter">Next chapter</string>
|
||||||
<string name="action_retry">Retry</string>
|
<string name="action_retry">Retry</string>
|
||||||
|
<string name="action_remove">Remove</string>
|
||||||
|
<string name="action_resume">Resume</string>
|
||||||
<string name="action_open_in_browser">Open in browser</string>
|
<string name="action_open_in_browser">Open in browser</string>
|
||||||
<string name="action_display_mode">Change display mode</string>
|
<string name="action_display_mode">Change display mode</string>
|
||||||
<string name="action_cancel">Cancel</string>
|
<string name="action_cancel">Cancel</string>
|
||||||
@ -248,6 +251,10 @@
|
|||||||
<string name="status">Status</string>
|
<string name="status">Status</string>
|
||||||
<string name="chapters">Chapters</string>
|
<string name="chapters">Chapters</string>
|
||||||
|
|
||||||
|
<!-- Dialog remove recently view -->
|
||||||
|
<string name="dialog_remove_recently_description">This will remove the read date of this chapter. Are you sure?</string>
|
||||||
|
<string name="dialog_remove_recently_reset">Reset all chapters for this manga</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Reader activity -->
|
<!-- Reader activity -->
|
||||||
<string name="downloading">Downloading…</string>
|
<string name="downloading">Downloading…</string>
|
||||||
@ -266,6 +273,9 @@
|
|||||||
<string name="backup_completed">Backup successfully restored</string>
|
<string name="backup_completed">Backup successfully restored</string>
|
||||||
<string name="restore_please_wait">Restoring backup. Please wait…</string>
|
<string name="restore_please_wait">Restoring backup. Please wait…</string>
|
||||||
|
|
||||||
|
<!-- Recent manga fragment -->
|
||||||
|
<string name="recent_manga_source">%1$s - Ch.%2$s</string>
|
||||||
|
|
||||||
<!-- Downloads activity and service -->
|
<!-- Downloads activity and service -->
|
||||||
<string name="download_queue_error">An error occurred while downloading chapters. You can try again in the downloads section</string>
|
<string name="download_queue_error">An error occurred while downloading chapters. You can try again in the downloads section</string>
|
||||||
|
|
||||||
@ -302,12 +312,13 @@
|
|||||||
<string name="update_check_notification_update_available">Update available</string>
|
<string name="update_check_notification_update_available">Update available</string>
|
||||||
|
|
||||||
<!--Content Description-->
|
<!--Content Description-->
|
||||||
<string name="description_backdrop">Backdrop image of selected manga</string>
|
<string name="description_backdrop">Backdrop image of manga</string>
|
||||||
<string name="description_cover">Cover of selected manga</string>
|
<string name="description_cover">Cover of manga</string>
|
||||||
|
|
||||||
<!-- Information Text -->
|
<!-- Information Text -->
|
||||||
<string name="information_no_downloads">No downloads</string>
|
<string name="information_no_downloads">No downloads</string>
|
||||||
<string name="information_no_recent">No recent chapters</string>
|
<string name="information_no_recent">No recent chapters</string>
|
||||||
|
<string name="information_no_recent_manga">No recently read manga</string>
|
||||||
<string name="information_empty_library">Empty library</string>
|
<string name="information_empty_library">Empty library</string>
|
||||||
|
|
||||||
<!-- Download Notification -->
|
<!-- Download Notification -->
|
||||||
@ -316,4 +327,5 @@
|
|||||||
<string name="download_notifier_page_error">A page is missing in directory</string>
|
<string name="download_notifier_page_error">A page is missing in directory</string>
|
||||||
<string name="download_notifier_page_ready_error">A page is not loaded</string>
|
<string name="download_notifier_page_ready_error">A page is not loaded</string>
|
||||||
<string name="download_notifier_text_only_wifi">No wifi connection available</string>
|
<string name="download_notifier_text_only_wifi">No wifi connection available</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -121,6 +121,10 @@
|
|||||||
<item name="android:textColor">?attr/colorAccent</item>
|
<item name="android:textColor">?attr/colorAccent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance.Medium.Button.Negative">
|
||||||
|
<item name="android:textColor">@color/md_red_500</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<!--=======-->
|
<!--=======-->
|
||||||
<!--Widgets-->
|
<!--Widgets-->
|
||||||
<!--=======-->
|
<!--=======-->
|
||||||
@ -137,6 +141,12 @@
|
|||||||
<item name="layout_behavior">eu.kanade.tachiyomi.widget.FABAnimationUpDown</item>
|
<item name="layout_behavior">eu.kanade.tachiyomi.widget.FABAnimationUpDown</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Theme.Widget.CardView">
|
||||||
|
<item name="android:layout_marginRight">@dimen/card_margin</item>
|
||||||
|
<item name="android:layout_marginLeft">@dimen/card_margin</item>
|
||||||
|
<item name="android:layout_marginTop">@dimen/card_margin</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Widget.GridView">
|
<style name="Theme.Widget.GridView">
|
||||||
<item name="android:padding">5dp</item>
|
<item name="android:padding">5dp</item>
|
||||||
<item name="android:clipToPadding">false</item>
|
<item name="android:clipToPadding">false</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user