mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-17 16:29:17 +01:00
JDK8, lint fixing (#2888)
* Use Kotlin JDK8 * Satisfy a ton of lints * Run res/layout files (and manifest) through reformatter
This commit is contained in:
parent
4fc8800a37
commit
415df2357c
@ -254,7 +254,7 @@ dependencies {
|
|||||||
testImplementation "org.robolectric:shadows-multidex:$robolectric_version"
|
testImplementation "org.robolectric:shadows-multidex:$robolectric_version"
|
||||||
testImplementation "org.robolectric:shadows-play-services:$robolectric_version"
|
testImplementation "org.robolectric:shadows-play-services:$robolectric_version"
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
final coroutines_version = '1.3.4'
|
final coroutines_version = '1.3.4'
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
|
@ -18,15 +18,15 @@
|
|||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:hasFragileUserData="true"
|
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:usesCleartextTraffic="true"
|
android:hasFragileUserData="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:requestLegacyExternalStorage="true"
|
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:theme="@style/Theme.Tachiyomi.Light">
|
android:requestLegacyExternalStorage="true"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:theme="@style/Theme.Tachiyomi.Light"
|
||||||
|
android:usesCleartextTraffic="true">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.main.MainActivity"
|
android:name=".ui.main.MainActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
@ -36,7 +36,9 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<!--suppress AndroidDomInspection -->
|
<!--suppress AndroidDomInspection -->
|
||||||
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
|
<meta-data
|
||||||
|
android:name="android.app.shortcuts"
|
||||||
|
android:resource="@xml/shortcuts" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.main.DeepLinkActivity"
|
android:name=".ui.main.DeepLinkActivity"
|
||||||
@ -44,17 +46,20 @@
|
|||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEARCH" />
|
<action android:name="android.intent.action.SEARCH" />
|
||||||
<action android:name="com.google.android.gms.actions.SEARCH_ACTION"/>
|
<action android:name="com.google.android.gms.actions.SEARCH_ACTION" />
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="eu.kanade.tachiyomi.SEARCH" />
|
<action android:name="eu.kanade.tachiyomi.SEARCH" />
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/>
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.app.searchable"
|
||||||
|
android:resource="@xml/searchable" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity android:name=".ui.reader.ReaderActivity" />
|
||||||
android:name=".ui.reader.ReaderActivity" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.security.BiometricUnlockActivity"
|
android:name=".ui.security.BiometricUnlockActivity"
|
||||||
android:theme="@style/Theme.Splash" />
|
android:theme="@style/Theme.Splash" />
|
||||||
@ -110,7 +115,7 @@
|
|||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".extension.util.ExtensionInstallActivity"
|
android:name=".extension.util.ExtensionInstallActivity"
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
|
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
@ -140,11 +145,11 @@
|
|||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".data.backup.BackupCreateService"
|
android:name=".data.backup.BackupCreateService"
|
||||||
android:exported="false"/>
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".data.backup.BackupRestoreService"
|
android:name=".data.backup.BackupRestoreService"
|
||||||
android:exported="false"/>
|
android:exported="false" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {
|
|||||||
val categoryEntries = JsonArray()
|
val categoryEntries = JsonArray()
|
||||||
|
|
||||||
// Add value's to root
|
// Add value's to root
|
||||||
root[Backup.VERSION] = Backup.CURRENT_VERSION
|
root[Backup.VERSION] = CURRENT_VERSION
|
||||||
root[Backup.MANGAS] = mangaEntries
|
root[Backup.MANGAS] = mangaEntries
|
||||||
root[CATEGORIES] = categoryEntries
|
root[CATEGORIES] = categoryEntries
|
||||||
|
|
||||||
@ -303,8 +303,8 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {
|
|||||||
fun restoreChapterFetchObservable(source: Source, manga: Manga, chapters: List<Chapter>): Observable<Pair<List<Chapter>, List<Chapter>>> {
|
fun restoreChapterFetchObservable(source: Source, manga: Manga, chapters: List<Chapter>): Observable<Pair<List<Chapter>, List<Chapter>>> {
|
||||||
return source.fetchChapterList(manga)
|
return source.fetchChapterList(manga)
|
||||||
.map { syncChaptersWithSource(databaseHelper, it, manga, source) }
|
.map { syncChaptersWithSource(databaseHelper, it, manga, source) }
|
||||||
.doOnNext {
|
.doOnNext { pair ->
|
||||||
if (it.first.isNotEmpty()) {
|
if (pair.first.isNotEmpty()) {
|
||||||
chapters.forEach { it.manga_id = manga.id }
|
chapters.forEach { it.manga_id = manga.id }
|
||||||
insertChapters(chapters)
|
insertChapters(chapters)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ class BackupRestoreService : Service() {
|
|||||||
* @return the start value of the command.
|
* @return the start value of the command.
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
if (intent == null) return Service.START_NOT_STICKY
|
if (intent == null) return START_NOT_STICKY
|
||||||
|
|
||||||
val uri = intent.getParcelableExtra<Uri>(BackupConst.EXTRA_URI)
|
val uri = intent.getParcelableExtra<Uri>(BackupConst.EXTRA_URI)
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ class BackupRestoreService : Service() {
|
|||||||
.subscribeOn(Schedulers.from(executor))
|
.subscribeOn(Schedulers.from(executor))
|
||||||
.subscribe()
|
.subscribe()
|
||||||
|
|
||||||
return Service.START_NOT_STICKY
|
return START_NOT_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,13 +80,13 @@ class ChapterCache(private val context: Context) {
|
|||||||
if (file == "journal" || file.startsWith("journal."))
|
if (file == "journal" || file.startsWith("journal."))
|
||||||
return false
|
return false
|
||||||
|
|
||||||
try {
|
return try {
|
||||||
// Remove the extension from the file to get the key of the cache
|
// Remove the extension from the file to get the key of the cache
|
||||||
val key = file.substringBeforeLast(".")
|
val key = file.substringBeforeLast(".")
|
||||||
// Remove file from cache.
|
// Remove file from cache.
|
||||||
return diskCache.remove(key)
|
diskCache.remove(key)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,10 +149,10 @@ class ChapterCache(private val context: Context) {
|
|||||||
* @return true if in cache otherwise false.
|
* @return true if in cache otherwise false.
|
||||||
*/
|
*/
|
||||||
fun isImageInCache(imageUrl: String): Boolean {
|
fun isImageInCache(imageUrl: String): Boolean {
|
||||||
try {
|
return try {
|
||||||
return diskCache.get(DiskUtil.hashKeyForDisk(imageUrl)) != null
|
diskCache.get(DiskUtil.hashKeyForDisk(imageUrl)) != null
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,17 +27,15 @@ class HistoryLastReadPutResolver : HistoryPutResolver() {
|
|||||||
|
|
||||||
val putResult: PutResult
|
val putResult: PutResult
|
||||||
|
|
||||||
try {
|
putResult = cursor.use { putCursor ->
|
||||||
if (cursor.count == 0) {
|
if (putCursor.count == 0) {
|
||||||
val insertQuery = mapToInsertQuery(history)
|
val insertQuery = mapToInsertQuery(history)
|
||||||
val insertedId = db.lowLevel().insert(insertQuery, mapToContentValues(history))
|
val insertedId = db.lowLevel().insert(insertQuery, mapToContentValues(history))
|
||||||
putResult = PutResult.newInsertResult(insertedId, insertQuery.table())
|
PutResult.newInsertResult(insertedId, insertQuery.table())
|
||||||
} else {
|
} else {
|
||||||
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, mapToUpdateContentValues(history))
|
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, mapToUpdateContentValues(history))
|
||||||
putResult = PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
|
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
cursor.close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
putResult
|
putResult
|
||||||
|
@ -259,7 +259,7 @@ class DownloadCache(
|
|||||||
*/
|
*/
|
||||||
private inline fun <K, V, R> Map<out K, V>.mapNotNullKeys(transform: (Map.Entry<K?, V>) -> R?): Map<R, V> {
|
private inline fun <K, V, R> Map<out K, V>.mapNotNullKeys(transform: (Map.Entry<K?, V>) -> R?): Map<R, V> {
|
||||||
val destination = LinkedHashMap<R, V>()
|
val destination = LinkedHashMap<R, V>()
|
||||||
forEach { element -> transform(element)?.let { destination.put(it, element.value) } }
|
forEach { element -> transform(element)?.let { destination[it] = element.value } }
|
||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ class DownloadService : Service() {
|
|||||||
* Not used.
|
* Not used.
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
return Service.START_NOT_STICKY
|
return START_NOT_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -283,7 +283,7 @@ class Downloader(
|
|||||||
// Do when page is downloaded.
|
// Do when page is downloaded.
|
||||||
.doOnNext { notifier.onProgressChange(download) }
|
.doOnNext { notifier.onProgressChange(download) }
|
||||||
.toList()
|
.toList()
|
||||||
.map { _ -> download }
|
.map { download }
|
||||||
// Do after download completes
|
// Do after download completes
|
||||||
.doOnNext { ensureSuccessfulDownload(download, mangaDir, tmpDir, chapterDirname) }
|
.doOnNext { ensureSuccessfulDownload(download, mangaDir, tmpDir, chapterDirname) }
|
||||||
// If the page list threw, it will resume here
|
// If the page list threw, it will resume here
|
||||||
|
@ -5,6 +5,7 @@ import android.util.Log
|
|||||||
import com.bumptech.glide.Priority
|
import com.bumptech.glide.Priority
|
||||||
import com.bumptech.glide.load.DataSource
|
import com.bumptech.glide.load.DataSource
|
||||||
import com.bumptech.glide.load.data.DataFetcher
|
import com.bumptech.glide.load.data.DataFetcher
|
||||||
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
@ -24,7 +25,7 @@ open class FileFetcher(private val file: File) : DataFetcher<InputStream> {
|
|||||||
data = FileInputStream(file)
|
data = FileInputStream(file)
|
||||||
} catch (e: FileNotFoundException) {
|
} catch (e: FileNotFoundException) {
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||||
Log.d(TAG, "Failed to open file", e)
|
Timber.d(e, "Failed to open file")
|
||||||
}
|
}
|
||||||
callback.onLoadFailed(e)
|
callback.onLoadFailed(e)
|
||||||
return
|
return
|
||||||
|
@ -246,7 +246,7 @@ class LibraryUpdateService(
|
|||||||
stopSelf(startId)
|
stopSelf(startId)
|
||||||
})
|
})
|
||||||
|
|
||||||
return Service.START_REDELIVER_INTENT
|
return START_REDELIVER_INTENT
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,13 +97,13 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
|
|||||||
// 100 point
|
// 100 point
|
||||||
POINT_100 -> index.toFloat()
|
POINT_100 -> index.toFloat()
|
||||||
// 5 stars
|
// 5 stars
|
||||||
POINT_5 -> when {
|
POINT_5 -> when (index) {
|
||||||
index == 0 -> 0f
|
0 -> 0f
|
||||||
else -> index * 20f - 10f
|
else -> index * 20f - 10f
|
||||||
}
|
}
|
||||||
// Smiley
|
// Smiley
|
||||||
POINT_3 -> when {
|
POINT_3 -> when (index) {
|
||||||
index == 0 -> 0f
|
0 -> 0f
|
||||||
else -> index * 25f + 10f
|
else -> index * 25f + 10f
|
||||||
}
|
}
|
||||||
// 10 point decimal
|
// 10 point decimal
|
||||||
@ -116,8 +116,8 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
|
|||||||
val score = track.score
|
val score = track.score
|
||||||
|
|
||||||
return when (scorePreference.getOrDefault()) {
|
return when (scorePreference.getOrDefault()) {
|
||||||
POINT_5 -> when {
|
POINT_5 -> when (score) {
|
||||||
score == 0f -> "0 ★"
|
0f -> "0 ★"
|
||||||
else -> "${((score + 10) / 20).toInt()} ★"
|
else -> "${((score + 10) / 20).toInt()} ★"
|
||||||
}
|
}
|
||||||
POINT_3 -> when {
|
POINT_3 -> when {
|
||||||
|
@ -38,7 +38,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||||||
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().serializeNulls().create()))
|
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().serializeNulls().create()))
|
||||||
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
||||||
.build()
|
.build()
|
||||||
.create(KitsuApi.Rest::class.java)
|
.create(Rest::class.java)
|
||||||
|
|
||||||
private val searchRest = Retrofit.Builder()
|
private val searchRest = Retrofit.Builder()
|
||||||
.baseUrl(algoliaKeyUrl)
|
.baseUrl(algoliaKeyUrl)
|
||||||
@ -46,7 +46,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
||||||
.build()
|
.build()
|
||||||
.create(KitsuApi.SearchKeyRest::class.java)
|
.create(SearchKeyRest::class.java)
|
||||||
|
|
||||||
private val algoliaRest = Retrofit.Builder()
|
private val algoliaRest = Retrofit.Builder()
|
||||||
.baseUrl(algoliaUrl)
|
.baseUrl(algoliaUrl)
|
||||||
@ -54,7 +54,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
||||||
.build()
|
.build()
|
||||||
.create(KitsuApi.AgoliaSearchRest::class.java)
|
.create(AgoliaSearchRest::class.java)
|
||||||
|
|
||||||
fun addLibManga(track: Track, userId: String): Observable<Track> {
|
fun addLibManga(track: Track, userId: String): Observable<Track> {
|
||||||
return Observable.defer {
|
return Observable.defer {
|
||||||
@ -162,7 +162,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
|
||||||
.build()
|
.build()
|
||||||
.create(KitsuApi.LoginRest::class.java)
|
.create(LoginRest::class.java)
|
||||||
.requestAccessToken(username, password)
|
.requestAccessToken(username, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ class KitsuSearchManga(obj: JsonObject) {
|
|||||||
cover_url = original ?: ""
|
cover_url = original ?: ""
|
||||||
summary = synopsis
|
summary = synopsis
|
||||||
tracking_url = KitsuApi.mangaUrl(media_id)
|
tracking_url = KitsuApi.mangaUrl(media_id)
|
||||||
if (endDate == null) {
|
publishing_status = if (endDate == null) {
|
||||||
publishing_status = "Publishing"
|
"Publishing"
|
||||||
} else {
|
} else {
|
||||||
publishing_status = "Finished"
|
"Finished"
|
||||||
}
|
}
|
||||||
publishing_type = subType ?: ""
|
publishing_type = subType ?: ""
|
||||||
start_date = startDate ?: ""
|
start_date = startDate ?: ""
|
||||||
|
@ -49,8 +49,7 @@ internal class ExtensionInstallReceiver(private val listener: Listener) :
|
|||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_PACKAGE_ADDED -> {
|
Intent.ACTION_PACKAGE_ADDED -> {
|
||||||
if (!isReplacing(intent)) launchNow {
|
if (!isReplacing(intent)) launchNow {
|
||||||
val result = getExtensionFromIntent(context, intent)
|
when (val result = getExtensionFromIntent(context, intent)) {
|
||||||
when (result) {
|
|
||||||
is LoadResult.Success -> listener.onExtensionInstalled(result.extension)
|
is LoadResult.Success -> listener.onExtensionInstalled(result.extension)
|
||||||
is LoadResult.Untrusted -> listener.onExtensionUntrusted(result.extension)
|
is LoadResult.Untrusted -> listener.onExtensionUntrusted(result.extension)
|
||||||
}
|
}
|
||||||
@ -58,8 +57,7 @@ internal class ExtensionInstallReceiver(private val listener: Listener) :
|
|||||||
}
|
}
|
||||||
Intent.ACTION_PACKAGE_REPLACED -> {
|
Intent.ACTION_PACKAGE_REPLACED -> {
|
||||||
launchNow {
|
launchNow {
|
||||||
val result = getExtensionFromIntent(context, intent)
|
when (val result = getExtensionFromIntent(context, intent)) {
|
||||||
when (result) {
|
|
||||||
is LoadResult.Success -> listener.onExtensionUpdated(result.extension)
|
is LoadResult.Success -> listener.onExtensionUpdated(result.extension)
|
||||||
// Not needed as a package can't be upgraded if the signature is different
|
// Not needed as a package can't be upgraded if the signature is different
|
||||||
is LoadResult.Untrusted -> {
|
is LoadResult.Untrusted -> {
|
||||||
|
@ -94,8 +94,7 @@ internal object ExtensionLoader {
|
|||||||
return LoadResult.Error(error)
|
return LoadResult.Error(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
val extName = pkgManager.getApplicationLabel(appInfo).toString()
|
val extName = pkgManager.getApplicationLabel(appInfo).toString().substringAfter("Tachiyomi: ")
|
||||||
.orEmpty().substringAfter("Tachiyomi: ")
|
|
||||||
val versionName = pkgInfo.versionName
|
val versionName = pkgInfo.versionName
|
||||||
val versionCode = pkgInfo.versionCode
|
val versionCode = pkgInfo.versionCode
|
||||||
|
|
||||||
@ -137,8 +136,7 @@ internal object ExtensionLoader {
|
|||||||
}
|
}
|
||||||
.flatMap {
|
.flatMap {
|
||||||
try {
|
try {
|
||||||
val obj = Class.forName(it, false, classLoader).newInstance()
|
when (val obj = Class.forName(it, false, classLoader).newInstance()) {
|
||||||
when (obj) {
|
|
||||||
is Source -> listOf(obj)
|
is Source -> listOf(obj)
|
||||||
is SourceFactory -> obj.createSources()
|
is SourceFactory -> obj.createSources()
|
||||||
else -> throw Exception("Unknown source class type! ${obj.javaClass}")
|
else -> throw Exception("Unknown source class type! ${obj.javaClass}")
|
||||||
|
@ -81,16 +81,16 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
val state = ((if (filters.isEmpty()) POPULAR_FILTERS else filters)[0] as OrderBy).state
|
val state = ((if (filters.isEmpty()) POPULAR_FILTERS else filters)[0] as OrderBy).state
|
||||||
when (state?.index) {
|
when (state?.index) {
|
||||||
0 -> {
|
0 -> {
|
||||||
if (state.ascending)
|
mangaDirs = if (state.ascending)
|
||||||
mangaDirs = mangaDirs.sortedBy { it.name.toLowerCase(Locale.ENGLISH) }
|
mangaDirs.sortedBy { it.name.toLowerCase(Locale.ENGLISH) }
|
||||||
else
|
else
|
||||||
mangaDirs = mangaDirs.sortedByDescending { it.name.toLowerCase(Locale.ENGLISH) }
|
mangaDirs.sortedByDescending { it.name.toLowerCase(Locale.ENGLISH) }
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
if (state.ascending)
|
mangaDirs = if (state.ascending)
|
||||||
mangaDirs = mangaDirs.sortedBy(File::lastModified)
|
mangaDirs.sortedBy(File::lastModified)
|
||||||
else
|
else
|
||||||
mangaDirs = mangaDirs.sortedByDescending(File::lastModified)
|
mangaDirs.sortedByDescending(File::lastModified)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,17 +131,14 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
getBaseDirectories(context)
|
getBaseDirectories(context)
|
||||||
.mapNotNull { File(it, manga.url).listFiles()?.toList() }
|
.mapNotNull { File(it, manga.url).listFiles()?.toList() }
|
||||||
.flatten()
|
.flatten()
|
||||||
.filter { it.extension.equals("json") }
|
.firstOrNull { it.extension == "json" }
|
||||||
.firstOrNull()
|
|
||||||
?.apply {
|
?.apply {
|
||||||
val json = Gson().fromJson(Scanner(this).useDelimiter("\\Z").next(), JsonObject::class.java)
|
val json = Gson().fromJson(Scanner(this).useDelimiter("\\Z").next(), JsonObject::class.java)
|
||||||
manga.title = json["title"]?.asString ?: manga.title
|
manga.title = json["title"]?.asString ?: manga.title
|
||||||
manga.author = json["author"]?.asString ?: manga.author
|
manga.author = json["author"]?.asString ?: manga.author
|
||||||
manga.artist = json["artist"]?.asString ?: manga.artist
|
manga.artist = json["artist"]?.asString ?: manga.artist
|
||||||
manga.description = json["description"]?.asString ?: manga.description
|
manga.description = json["description"]?.asString ?: manga.description
|
||||||
manga.genre = json["genre"]?.asJsonArray
|
manga.genre = json["genre"]?.asJsonArray?.joinToString(", ") { it.asString }
|
||||||
?.map { it.asString }
|
|
||||||
?.joinToString(", ")
|
|
||||||
?: manga.genre
|
?: manga.genre
|
||||||
manga.status = json["status"]?.asInt ?: manga.status
|
manga.status = json["status"]?.asInt ?: manga.status
|
||||||
}
|
}
|
||||||
@ -150,6 +147,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
|
|
||||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||||
val chapters = getBaseDirectories(context)
|
val chapters = getBaseDirectories(context)
|
||||||
|
.asSequence()
|
||||||
.mapNotNull { File(it, manga.url).listFiles()?.toList() }
|
.mapNotNull { File(it, manga.url).listFiles()?.toList() }
|
||||||
.flatten()
|
.flatten()
|
||||||
.filter { it.isDirectory || isSupportedFile(it.extension) }
|
.filter { it.isDirectory || isSupportedFile(it.extension) }
|
||||||
@ -171,6 +169,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
val c = c2.chapter_number.compareTo(c1.chapter_number)
|
val c = c2.chapter_number.compareTo(c1.chapter_number)
|
||||||
if (c == 0) c2.name.compareToCaseInsensitiveNaturalOrder(c1.name) else c
|
if (c == 0) c2.name.compareToCaseInsensitiveNaturalOrder(c1.name) else c
|
||||||
})
|
})
|
||||||
|
.toList()
|
||||||
|
|
||||||
return Observable.just(chapters)
|
return Observable.just(chapters)
|
||||||
}
|
}
|
||||||
@ -211,8 +210,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCover(chapter: SChapter, manga: SManga): File? {
|
private fun updateCover(chapter: SChapter, manga: SManga): File? {
|
||||||
val format = getFormat(chapter)
|
return when (val format = getFormat(chapter)) {
|
||||||
return when (format) {
|
|
||||||
is Format.Directory -> {
|
is Format.Directory -> {
|
||||||
val entry = format.file.listFiles()
|
val entry = format.file.listFiles()
|
||||||
.sortedWith(Comparator<File> { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) })
|
.sortedWith(Comparator<File> { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) })
|
||||||
@ -250,7 +248,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OrderBy : Filter.Sort("Order by", arrayOf("Title", "Date"), Filter.Sort.Selection(0, true))
|
private class OrderBy : Filter.Sort("Order by", arrayOf("Title", "Date"), Selection(0, true))
|
||||||
|
|
||||||
override fun getFilterList() = FilterList(OrderBy())
|
override fun getFilterList() = FilterList(OrderBy())
|
||||||
|
|
||||||
|
@ -207,14 +207,14 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
* @param manga the manga to look for chapters.
|
* @param manga the manga to look for chapters.
|
||||||
*/
|
*/
|
||||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||||
if (manga.status != SManga.LICENSED) {
|
return if (manga.status != SManga.LICENSED) {
|
||||||
return client.newCall(chapterListRequest(manga))
|
client.newCall(chapterListRequest(manga))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
chapterListParse(response)
|
chapterListParse(response)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Observable.error(Exception("Licensed - No chapters to show"))
|
Observable.error(Exception("Licensed - No chapters to show"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,16 +340,16 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
* @param orig the full url.
|
* @param orig the full url.
|
||||||
*/
|
*/
|
||||||
private fun getUrlWithoutDomain(orig: String): String {
|
private fun getUrlWithoutDomain(orig: String): String {
|
||||||
try {
|
return try {
|
||||||
val uri = URI(orig)
|
val uri = URI(orig)
|
||||||
var out = uri.path
|
var out = uri.path
|
||||||
if (uri.query != null)
|
if (uri.query != null)
|
||||||
out += "?" + uri.query
|
out += "?" + uri.query
|
||||||
if (uri.fragment != null)
|
if (uri.fragment != null)
|
||||||
out += "#" + uri.fragment
|
out += "#" + uri.fragment
|
||||||
return out
|
out
|
||||||
} catch (e: URISyntaxException) {
|
} catch (e: URISyntaxException) {
|
||||||
return orig
|
orig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,13 +31,13 @@ interface SlicedHolder {
|
|||||||
|
|
||||||
when {
|
when {
|
||||||
// Only one item in the card
|
// Only one item in the card
|
||||||
count == 1 -> applySlice(2f, false, false, true, true)
|
count == 1 -> applySlice(2f, topRect = false, bottomRect = false, topShadow = true, bottomShadow = true)
|
||||||
// First item of the card
|
// First item of the card
|
||||||
position == 0 -> applySlice(2f, false, true, true, false)
|
position == 0 -> applySlice(2f, topRect = false, bottomRect = true, topShadow = true, bottomShadow = false)
|
||||||
// Last item of the card
|
// Last item of the card
|
||||||
position == count - 1 -> applySlice(2f, true, false, false, true)
|
position == count - 1 -> applySlice(2f, topRect = true, bottomRect = false, topShadow = false, bottomShadow = true)
|
||||||
// Middle item
|
// Middle item
|
||||||
else -> applySlice(0f, false, false, false, false)
|
else -> applySlice(0f, topRect = false, bottomRect = false, topShadow = false, bottomShadow = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class ExtensionAdapter(val controller: ExtensionController) :
|
|||||||
/**
|
/**
|
||||||
* Listener for browse item clicks.
|
* Listener for browse item clicks.
|
||||||
*/
|
*/
|
||||||
val buttonClickListener: ExtensionAdapter.OnButtonClickListener = controller
|
val buttonClickListener: OnButtonClickListener = controller
|
||||||
|
|
||||||
interface OnButtonClickListener {
|
interface OnButtonClickListener {
|
||||||
fun onButtonClick(position: Int)
|
fun onButtonClick(position: Int)
|
||||||
|
@ -229,13 +229,13 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
|||||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||||
// If the action mode is created and the position is valid, toggle the selection.
|
// If the action mode is created and the position is valid, toggle the selection.
|
||||||
val item = adapter.getItem(position) ?: return false
|
val item = adapter.getItem(position) ?: return false
|
||||||
if (adapter.mode == SelectableAdapter.Mode.MULTI) {
|
return if (adapter.mode == SelectableAdapter.Mode.MULTI) {
|
||||||
lastClickPosition = position
|
lastClickPosition = position
|
||||||
toggleSelection(position)
|
toggleSelection(position)
|
||||||
return true
|
true
|
||||||
} else {
|
} else {
|
||||||
openManga(item.manga)
|
openManga(item.manga)
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ class LibraryPresenter(
|
|||||||
if (mangas.isEmpty()) return emptyList()
|
if (mangas.isEmpty()) return emptyList()
|
||||||
return mangas.toSet()
|
return mangas.toSet()
|
||||||
.map { db.getCategoriesForManga(it).executeAsBlocking() }
|
.map { db.getCategoriesForManga(it).executeAsBlocking() }
|
||||||
.reduce { set1: Iterable<Category>, set2 -> set1.intersect(set2) }
|
.reduce { set1: Iterable<Category>, set2 -> set1.intersect(set2).toMutableList() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,13 +306,13 @@ class ChaptersController : NucleusController<ChaptersControllerBinding, Chapters
|
|||||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||||
val adapter = adapter ?: return false
|
val adapter = adapter ?: return false
|
||||||
val item = adapter.getItem(position) ?: return false
|
val item = adapter.getItem(position) ?: return false
|
||||||
if (actionMode != null && adapter.mode == SelectableAdapter.Mode.MULTI) {
|
return if (actionMode != null && adapter.mode == SelectableAdapter.Mode.MULTI) {
|
||||||
lastClickPosition = position
|
lastClickPosition = position
|
||||||
toggleSelection(position)
|
toggleSelection(position)
|
||||||
return true
|
true
|
||||||
} else {
|
} else {
|
||||||
openChapter(item.chapter)
|
openChapter(item.chapter)
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +67,8 @@ class ChaptersPresenter(
|
|||||||
// Prepare the relay.
|
// Prepare the relay.
|
||||||
chaptersRelay.flatMap { applyChapterFilters(it) }
|
chaptersRelay.flatMap { applyChapterFilters(it) }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribeLatestCache(ChaptersController::onNextChapters,
|
.subscribeLatestCache(ChaptersController::onNextChapters)
|
||||||
{ _, error -> Timber.e(error) })
|
{ _, error -> Timber.e(error) }
|
||||||
|
|
||||||
// Add the subscription that retrieves the chapters from the database, keeps subscribed to
|
// Add the subscription that retrieves the chapters from the database, keeps subscribed to
|
||||||
// changes, and sends the list of chapters to the relay.
|
// changes, and sends the list of chapters to the relay.
|
||||||
|
@ -262,13 +262,11 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
|||||||
.centerCrop()
|
.centerCrop()
|
||||||
.into(binding.mangaCover)
|
.into(binding.mangaCover)
|
||||||
|
|
||||||
if (binding.backdrop != null) {
|
|
||||||
GlideApp.with(view.context)
|
GlideApp.with(view.context)
|
||||||
.load(manga)
|
.load(manga)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
.into(binding.backdrop!!)
|
.into(binding.backdrop)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manga info section
|
// Manga info section
|
||||||
@ -618,8 +616,7 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val previousController = router.backstack[router.backstackSize - 2].controller()
|
when (val previousController = router.backstack[router.backstackSize - 2].controller()) {
|
||||||
when (previousController) {
|
|
||||||
is LibraryController -> {
|
is LibraryController -> {
|
||||||
router.handleBack()
|
router.handleBack()
|
||||||
previousController.search(query)
|
previousController.search(query)
|
||||||
|
@ -33,7 +33,7 @@ class SetTrackStatusDialog<T> : DialogController
|
|||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
val item = item
|
val item = item
|
||||||
val statusList = item.service.getStatusList()
|
val statusList = item.service.getStatusList()
|
||||||
val statusString = statusList.mapNotNull { item.service.getStatus(it) }
|
val statusString = statusList.map { item.service.getStatus(it) }
|
||||||
val selectedIndex = statusList.indexOf(item.track?.status)
|
val selectedIndex = statusList.indexOf(item.track?.status)
|
||||||
|
|
||||||
return MaterialDialog.Builder(activity!!)
|
return MaterialDialog.Builder(activity!!)
|
||||||
|
@ -90,7 +90,7 @@ class TrackController : NucleusController<TrackControllerBinding, TrackPresenter
|
|||||||
override fun onLogoClick(position: Int) {
|
override fun onLogoClick(position: Int) {
|
||||||
val track = adapter?.getItem(position)?.track ?: return
|
val track = adapter?.getItem(position)?.track ?: return
|
||||||
|
|
||||||
if (track.tracking_url.isNullOrBlank()) {
|
if (track.tracking_url.isBlank()) {
|
||||||
activity?.toast(R.string.url_not_set)
|
activity?.toast(R.string.url_not_set)
|
||||||
} else {
|
} else {
|
||||||
activity?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(track.tracking_url)))
|
activity?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(track.tracking_url)))
|
||||||
|
@ -54,7 +54,7 @@ class TrackSearchAdapter(context: Context) :
|
|||||||
view.track_search_title.text = track.title
|
view.track_search_title.text = track.title
|
||||||
view.track_search_summary.text = track.summary
|
view.track_search_summary.text = track.summary
|
||||||
GlideApp.with(view.context).clear(view.track_search_cover)
|
GlideApp.with(view.context).clear(view.track_search_cover)
|
||||||
if (!track.cover_url.isNullOrEmpty()) {
|
if (!track.cover_url.isEmpty()) {
|
||||||
GlideApp.with(view.context)
|
GlideApp.with(view.context)
|
||||||
.load(track.cover_url)
|
.load(track.cover_url)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||||
@ -62,21 +62,21 @@ class TrackSearchAdapter(context: Context) :
|
|||||||
.into(view.track_search_cover)
|
.into(view.track_search_cover)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (track.publishing_status.isNullOrBlank()) {
|
if (track.publishing_status.isBlank()) {
|
||||||
view.track_search_status.gone()
|
view.track_search_status.gone()
|
||||||
view.track_search_status_result.gone()
|
view.track_search_status_result.gone()
|
||||||
} else {
|
} else {
|
||||||
view.track_search_status_result.text = track.publishing_status.capitalize()
|
view.track_search_status_result.text = track.publishing_status.capitalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (track.publishing_type.isNullOrBlank()) {
|
if (track.publishing_type.isBlank()) {
|
||||||
view.track_search_type.gone()
|
view.track_search_type.gone()
|
||||||
view.track_search_type_result.gone()
|
view.track_search_type_result.gone()
|
||||||
} else {
|
} else {
|
||||||
view.track_search_type_result.text = track.publishing_type.capitalize()
|
view.track_search_type_result.text = track.publishing_type.capitalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (track.start_date.isNullOrBlank()) {
|
if (track.start_date.isBlank()) {
|
||||||
view.track_search_start.gone()
|
view.track_search_start.gone()
|
||||||
view.track_search_start_result.gone()
|
view.track_search_start_result.gone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,8 +9,8 @@ import kotlinx.android.synthetic.main.source_list_item.thumbnail
|
|||||||
import kotlinx.android.synthetic.main.source_list_item.title
|
import kotlinx.android.synthetic.main.source_list_item.title
|
||||||
|
|
||||||
class MangaHolder(
|
class MangaHolder(
|
||||||
private val view: View,
|
view: View,
|
||||||
private val adapter: FlexibleAdapter<*>
|
adapter: FlexibleAdapter<*>
|
||||||
) : BaseFlexibleViewHolder(view, adapter) {
|
) : BaseFlexibleViewHolder(view, adapter) {
|
||||||
|
|
||||||
fun bind(item: MangaItem) {
|
fun bind(item: MangaItem) {
|
||||||
|
@ -25,7 +25,7 @@ class SelectionHeader : AbstractHeaderItem<SelectionHeader.Holder>() {
|
|||||||
* Creates a new view holder for this item.
|
* Creates a new view holder for this item.
|
||||||
*/
|
*/
|
||||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): Holder {
|
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): Holder {
|
||||||
return SelectionHeader.Holder(view, adapter)
|
return Holder(view, adapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,7 +171,7 @@ class AboutController : SettingsController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getFormattedBuildTime(): String {
|
private fun getFormattedBuildTime(): String {
|
||||||
try {
|
return try {
|
||||||
val inputDf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US)
|
val inputDf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US)
|
||||||
inputDf.timeZone = TimeZone.getTimeZone("UTC")
|
inputDf.timeZone = TimeZone.getTimeZone("UTC")
|
||||||
val buildTime = inputDf.parse(BuildConfig.BUILD_TIME)
|
val buildTime = inputDf.parse(BuildConfig.BUILD_TIME)
|
||||||
@ -180,9 +180,9 @@ class AboutController : SettingsController() {
|
|||||||
DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault())
|
DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault())
|
||||||
outputDf.timeZone = TimeZone.getDefault()
|
outputDf.timeZone = TimeZone.getDefault()
|
||||||
|
|
||||||
return buildTime.toDateTimestampString(dateFormat)
|
buildTime.toDateTimestampString(dateFormat)
|
||||||
} catch (e: ParseException) {
|
} catch (e: ParseException) {
|
||||||
return BuildConfig.BUILD_TIME
|
BuildConfig.BUILD_TIME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import android.text.Spannable
|
|||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.style.ScaleXSpan
|
import android.text.style.ScaleXSpan
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
import eu.kanade.tachiyomi.widget.OutlineSpan
|
import eu.kanade.tachiyomi.widget.OutlineSpan
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ class PageIndicatorTextView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.setText(finalText, TextView.BufferType.SPANNABLE)
|
super.setText(finalText, BufferType.SPANNABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
@ -361,7 +361,7 @@ class ReaderPresenter(
|
|||||||
|
|
||||||
if (selectedChapter != currentChapters.currChapter) {
|
if (selectedChapter != currentChapters.currChapter) {
|
||||||
Timber.d("Setting ${selectedChapter.chapter.url} as active")
|
Timber.d("Setting ${selectedChapter.chapter.url} as active")
|
||||||
onChapterChanged(currentChapters.currChapter, selectedChapter)
|
onChapterChanged(currentChapters.currChapter)
|
||||||
loadNewChapter(selectedChapter)
|
loadNewChapter(selectedChapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,7 +370,7 @@ class ReaderPresenter(
|
|||||||
* Called when a chapter changed from [fromChapter] to [toChapter]. It updates [fromChapter]
|
* Called when a chapter changed from [fromChapter] to [toChapter]. It updates [fromChapter]
|
||||||
* on the database.
|
* on the database.
|
||||||
*/
|
*/
|
||||||
private fun onChapterChanged(fromChapter: ReaderChapter, toChapter: ReaderChapter) {
|
private fun onChapterChanged(fromChapter: ReaderChapter) {
|
||||||
saveChapterProgress(fromChapter)
|
saveChapterProgress(fromChapter)
|
||||||
saveChapterHistory(fromChapter)
|
saveChapterHistory(fromChapter)
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,10 @@ class ChapterLoader(
|
|||||||
return Observable.just(chapter)
|
return Observable.just(chapter)
|
||||||
.doOnNext { chapter.state = ReaderChapter.State.Loading }
|
.doOnNext { chapter.state = ReaderChapter.State.Loading }
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMap {
|
.flatMap { readerChapter ->
|
||||||
Timber.d("Loading pages for ${chapter.chapter.name}")
|
Timber.d("Loading pages for ${chapter.chapter.name}")
|
||||||
|
|
||||||
val loader = getPageLoader(it)
|
val loader = getPageLoader(readerChapter)
|
||||||
chapter.pageLoader = loader
|
chapter.pageLoader = loader
|
||||||
|
|
||||||
loader.getPages().take(1).doOnNext { pages ->
|
loader.getPages().take(1).doOnNext { pages ->
|
||||||
|
@ -122,7 +122,7 @@ class ReaderProgressBar @JvmOverloads constructor(
|
|||||||
*/
|
*/
|
||||||
override fun setVisibility(visibility: Int) {
|
override fun setVisibility(visibility: Int) {
|
||||||
super.setVisibility(visibility)
|
super.setVisibility(visibility)
|
||||||
val isVisible = visibility == View.VISIBLE
|
val isVisible = visibility == VISIBLE
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
startAnimation()
|
startAnimation()
|
||||||
} else {
|
} else {
|
||||||
@ -134,7 +134,7 @@ class ReaderProgressBar @JvmOverloads constructor(
|
|||||||
* Starts the rotation animation if needed.
|
* Starts the rotation animation if needed.
|
||||||
*/
|
*/
|
||||||
private fun startAnimation() {
|
private fun startAnimation() {
|
||||||
if (visibility != View.VISIBLE || windowVisibility != View.VISIBLE || animation != null) {
|
if (visibility != VISIBLE || windowVisibility != VISIBLE || animation != null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ class ReaderProgressBar @JvmOverloads constructor(
|
|||||||
* Hides this progress bar with an optional fade out if [animate] is true.
|
* Hides this progress bar with an optional fade out if [animate] is true.
|
||||||
*/
|
*/
|
||||||
fun hide(animate: Boolean = false) {
|
fun hide(animate: Boolean = false) {
|
||||||
if (visibility == View.GONE) return
|
if (visibility == GONE) return
|
||||||
|
|
||||||
if (!animate) {
|
if (!animate) {
|
||||||
gone()
|
gone()
|
||||||
|
@ -285,7 +285,7 @@ class PagerPageHolder(
|
|||||||
return ReaderProgressBar(context, null).apply {
|
return ReaderProgressBar(context, null).apply {
|
||||||
|
|
||||||
val size = 48.dpToPx
|
val size = 48.dpToPx
|
||||||
layoutParams = FrameLayout.LayoutParams(size, size).apply {
|
layoutParams = LayoutParams(size, size).apply {
|
||||||
gravity = Gravity.CENTER
|
gravity = Gravity.CENTER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,7 +300,7 @@ class PagerPageHolder(
|
|||||||
val config = viewer.config
|
val config = viewer.config
|
||||||
|
|
||||||
subsamplingImageView = SubsamplingScaleImageView(context).apply {
|
subsamplingImageView = SubsamplingScaleImageView(context).apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
||||||
setMaxTileSize(viewer.activity.maxBitmapSize)
|
setMaxTileSize(viewer.activity.maxBitmapSize)
|
||||||
setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER)
|
setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER)
|
||||||
setDoubleTapZoomDuration(config.doubleTapAnimDuration)
|
setDoubleTapZoomDuration(config.doubleTapAnimDuration)
|
||||||
@ -335,7 +335,7 @@ class PagerPageHolder(
|
|||||||
if (imageView != null) return imageView!!
|
if (imageView != null) return imageView!!
|
||||||
|
|
||||||
imageView = PhotoView(context, null).apply {
|
imageView = PhotoView(context, null).apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
||||||
adjustViewBounds = true
|
adjustViewBounds = true
|
||||||
setZoomTransitionDuration(viewer.config.doubleTapAnimDuration)
|
setZoomTransitionDuration(viewer.config.doubleTapAnimDuration)
|
||||||
setScaleLevels(1f, 2f, 3f)
|
setScaleLevels(1f, 2f, 3f)
|
||||||
@ -362,7 +362,7 @@ class PagerPageHolder(
|
|||||||
if (retryButton != null) return retryButton!!
|
if (retryButton != null) return retryButton!!
|
||||||
|
|
||||||
retryButton = PagerButton(context, viewer).apply {
|
retryButton = PagerButton(context, viewer).apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
||||||
gravity = Gravity.CENTER
|
gravity = Gravity.CENTER
|
||||||
}
|
}
|
||||||
setText(R.string.action_retry)
|
setText(R.string.action_retry)
|
||||||
@ -399,7 +399,7 @@ class PagerPageHolder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
PagerButton(context, viewer).apply {
|
PagerButton(context, viewer).apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
||||||
setMargins(margins, margins, margins, margins)
|
setMargins(margins, margins, margins, margins)
|
||||||
}
|
}
|
||||||
setText(R.string.action_retry)
|
setText(R.string.action_retry)
|
||||||
@ -413,7 +413,7 @@ class PagerPageHolder(
|
|||||||
val imageUrl = page.imageUrl
|
val imageUrl = page.imageUrl
|
||||||
if (imageUrl.orEmpty().startsWith("http")) {
|
if (imageUrl.orEmpty().startsWith("http")) {
|
||||||
PagerButton(context, viewer).apply {
|
PagerButton(context, viewer).apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
||||||
setMargins(margins, margins, margins, margins)
|
setMargins(margins, margins, margins, margins)
|
||||||
}
|
}
|
||||||
setText(R.string.action_open_in_web_view)
|
setText(R.string.action_open_in_web_view)
|
||||||
|
@ -55,7 +55,7 @@ class PagerTransitionHolder(
|
|||||||
* dynamically.
|
* dynamically.
|
||||||
*/
|
*/
|
||||||
private var pagesContainer = LinearLayout(context).apply {
|
private var pagesContainer = LinearLayout(context).apply {
|
||||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||||
orientation = VERTICAL
|
orientation = VERTICAL
|
||||||
gravity = Gravity.CENTER
|
gravity = Gravity.CENTER
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
|
|||||||
*/
|
*/
|
||||||
private fun setChaptersInternal(chapters: ViewerChapters) {
|
private fun setChaptersInternal(chapters: ViewerChapters) {
|
||||||
Timber.d("setChaptersInternal")
|
Timber.d("setChaptersInternal")
|
||||||
var forceTransition = config.alwaysShowChapterTransition || adapter.items.getOrNull(pager.currentItem) is ChapterTransition
|
val forceTransition = config.alwaysShowChapterTransition || adapter.items.getOrNull(pager.currentItem) is ChapterTransition
|
||||||
adapter.setChapters(chapters, forceTransition)
|
adapter.setChapters(chapters, forceTransition)
|
||||||
|
|
||||||
// Layout the pager once a chapter is being set
|
// Layout the pager once a chapter is being set
|
||||||
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager
|
|||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.viewpager.widget.PagerAdapter
|
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
@ -93,8 +92,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
|||||||
* Creates a new view for the item at the given [position].
|
* Creates a new view for the item at the given [position].
|
||||||
*/
|
*/
|
||||||
override fun createView(container: ViewGroup, position: Int): View {
|
override fun createView(container: ViewGroup, position: Int): View {
|
||||||
val item = items[position]
|
return when (val item = items[position]) {
|
||||||
return when (item) {
|
|
||||||
is ReaderPage -> PagerPageHolder(viewer, item)
|
is ReaderPage -> PagerPageHolder(viewer, item)
|
||||||
is ChapterTransition -> PagerTransitionHolder(viewer, item)
|
is ChapterTransition -> PagerTransitionHolder(viewer, item)
|
||||||
else -> throw NotImplementedError("Holder for ${item.javaClass} not implemented")
|
else -> throw NotImplementedError("Holder for ${item.javaClass} not implemented")
|
||||||
@ -113,6 +111,6 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
|||||||
Timber.d("Position for ${view.item} not found")
|
Timber.d("Position for ${view.item} not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PagerAdapter.POSITION_NONE
|
return POSITION_NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,8 +82,7 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
|
|||||||
* Returns the view type for the item at the given [position].
|
* Returns the view type for the item at the given [position].
|
||||||
*/
|
*/
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
val item = items[position]
|
return when (val item = items[position]) {
|
||||||
return when (item) {
|
|
||||||
is ReaderPage -> PAGE_VIEW
|
is ReaderPage -> PAGE_VIEW
|
||||||
is ChapterTransition -> TRANSITION_VIEW
|
is ChapterTransition -> TRANSITION_VIEW
|
||||||
else -> error("Unknown view type for ${item.javaClass}")
|
else -> error("Unknown view type for ${item.javaClass}")
|
||||||
|
@ -202,7 +202,7 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
|
|||||||
*/
|
*/
|
||||||
override fun setChapters(chapters: ViewerChapters) {
|
override fun setChapters(chapters: ViewerChapters) {
|
||||||
Timber.d("setChapters")
|
Timber.d("setChapters")
|
||||||
var forceTransition = config.alwaysShowChapterTransition || currentPage is ChapterTransition
|
val forceTransition = config.alwaysShowChapterTransition || currentPage is ChapterTransition
|
||||||
adapter.setChapters(chapters, forceTransition)
|
adapter.setChapters(chapters, forceTransition)
|
||||||
|
|
||||||
if (recycler.visibility == View.GONE) {
|
if (recycler.visibility == View.GONE) {
|
||||||
|
@ -53,9 +53,9 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
val map = TreeMap<Date, MutableList<MangaChapterHistory>> { d1, d2 -> d2.compareTo(d1) }
|
val map = TreeMap<Date, MutableList<MangaChapterHistory>> { d1, d2 -> d2.compareTo(d1) }
|
||||||
val byDay = recents
|
val byDay = recents
|
||||||
.groupByTo(map, { it.history.last_read.toDateKey() })
|
.groupByTo(map, { it.history.last_read.toDateKey() })
|
||||||
byDay.flatMap {
|
byDay.flatMap { entry ->
|
||||||
val dateItem = DateSectionItem(it.key)
|
val dateItem = DateSectionItem(entry.key)
|
||||||
it.value.map { HistoryItem(it, dateItem) }
|
entry.value.map { HistoryItem(it, dateItem) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -102,7 +102,7 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val chapters = db.getChapters(manga).executeAsBlocking()
|
val chapters = db.getChapters(manga).executeAsBlocking()
|
||||||
.sortedWith(Comparator<Chapter> { c1, c2 -> sortFunction(c1, c2) })
|
.sortedWith(Comparator { c1, c2 -> sortFunction(c1, c2) })
|
||||||
|
|
||||||
val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }
|
val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }
|
||||||
return when (manga.sorting) {
|
return when (manga.sorting) {
|
||||||
|
@ -156,12 +156,12 @@ class UpdatesController : NucleusController<UpdatesControllerBinding, UpdatesPre
|
|||||||
|
|
||||||
// Get item from position
|
// Get item from position
|
||||||
val item = adapter.getItem(position) as? UpdatesItem ?: return false
|
val item = adapter.getItem(position) as? UpdatesItem ?: return false
|
||||||
if (actionMode != null && adapter.mode == SelectableAdapter.Mode.MULTI) {
|
return if (actionMode != null && adapter.mode == SelectableAdapter.Mode.MULTI) {
|
||||||
toggleSelection(position)
|
toggleSelection(position)
|
||||||
return true
|
true
|
||||||
} else {
|
} else {
|
||||||
openChapter(item)
|
openChapter(item)
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,15 +63,15 @@ class UpdatesPresenter(
|
|||||||
val map = TreeMap<Date, MutableList<MangaChapter>> { d1, d2 -> d2.compareTo(d1) }
|
val map = TreeMap<Date, MutableList<MangaChapter>> { d1, d2 -> d2.compareTo(d1) }
|
||||||
val byDay = mangaChapters
|
val byDay = mangaChapters
|
||||||
.groupByTo(map, { it.chapter.date_fetch.toDateKey() })
|
.groupByTo(map, { it.chapter.date_fetch.toDateKey() })
|
||||||
byDay.flatMap {
|
byDay.flatMap { entry ->
|
||||||
val dateItem = DateSectionItem(it.key)
|
val dateItem = DateSectionItem(entry.key)
|
||||||
it.value
|
entry.value
|
||||||
.sortedWith(compareBy({ it.chapter.date_fetch }, { it.chapter.chapter_number })).asReversed()
|
.sortedWith(compareBy({ it.chapter.date_fetch }, { it.chapter.chapter_number })).asReversed()
|
||||||
.map { UpdatesItem(it.chapter, it.manga, dateItem) }
|
.map { UpdatesItem(it.chapter, it.manga, dateItem) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.doOnNext {
|
.doOnNext { list ->
|
||||||
it.forEach { item ->
|
list.forEach { item ->
|
||||||
// Find an active download for this chapter.
|
// Find an active download for this chapter.
|
||||||
val download = downloadManager.queue.find { it.chapter.id == item.chapter.id }
|
val download = downloadManager.queue.find { it.chapter.id == item.chapter.id }
|
||||||
|
|
||||||
@ -81,8 +81,8 @@ class UpdatesPresenter(
|
|||||||
item.download = download
|
item.download = download
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setDownloadedChapters(it)
|
setDownloadedChapters(list)
|
||||||
chapters = it
|
chapters = list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +101,8 @@ class SettingsDownloadController : SettingsController() {
|
|||||||
.subscribeUntilDestroy { isVisible = it }
|
.subscribeUntilDestroy { isVisible = it }
|
||||||
|
|
||||||
preferences.downloadNewCategories().asObservable()
|
preferences.downloadNewCategories().asObservable()
|
||||||
.subscribeUntilDestroy {
|
.subscribeUntilDestroy { mutableSet ->
|
||||||
val selectedCategories = it
|
val selectedCategories = mutableSet
|
||||||
.mapNotNull { id -> categories.find { it.id == id.toInt() } }
|
.mapNotNull { id -> categories.find { it.id == id.toInt() } }
|
||||||
.sortedBy { it.order }
|
.sortedBy { it.order }
|
||||||
|
|
||||||
|
@ -118,8 +118,8 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
entries = categories.map { it.name }.toTypedArray()
|
entries = categories.map { it.name }.toTypedArray()
|
||||||
entryValues = categories.map { it.id.toString() }.toTypedArray()
|
entryValues = categories.map { it.id.toString() }.toTypedArray()
|
||||||
preferences.libraryUpdateCategories().asObservable()
|
preferences.libraryUpdateCategories().asObservable()
|
||||||
.subscribeUntilDestroy {
|
.subscribeUntilDestroy { mutableSet ->
|
||||||
val selectedCategories = it
|
val selectedCategories = mutableSet
|
||||||
.mapNotNull { id -> categories.find { it.id == id.toInt() } }
|
.mapNotNull { id -> categories.find { it.id == id.toInt() } }
|
||||||
.sortedBy { it.order }
|
.sortedBy { it.order }
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ class SourcePresenter(
|
|||||||
sharedObs.take(1),
|
sharedObs.take(1),
|
||||||
sharedObs.skip(1).delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()))
|
sharedObs.skip(1).delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()))
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.map { (sourceManager.get(it) as? CatalogueSource)?.let { SourceItem(it) } }
|
.map { item -> (sourceManager.get(item) as? CatalogueSource)?.let { SourceItem(it) } }
|
||||||
.subscribeLatestCache(SourceController::setLastUsedSource)
|
.subscribeLatestCache(SourceController::setLastUsedSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,9 +149,9 @@ open class BrowseSourcePresenter(
|
|||||||
pagerSubscription?.let { remove(it) }
|
pagerSubscription?.let { remove(it) }
|
||||||
pagerSubscription = pager.results()
|
pagerSubscription = pager.results()
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.map { it.first to it.second.map { networkToLocalManga(it, sourceId) } }
|
.map { pair -> pair.first to pair.second.map { networkToLocalManga(it, sourceId) } }
|
||||||
.doOnNext { initializeMangas(it.second) }
|
.doOnNext { initializeMangas(it.second) }
|
||||||
.map { it.first to it.second.map { SourceItem(it, catalogueAsList) } }
|
.map { pair -> pair.first to pair.second.map { SourceItem(it, catalogueAsList) } }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribeReplay({ view, (page, mangas) ->
|
.subscribeReplay({ view, (page, mangas) ->
|
||||||
view.onAddPage(page, mangas)
|
view.onAddPage(page, mangas)
|
||||||
@ -292,17 +292,17 @@ open class BrowseSourcePresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FilterList.toItems(): List<IFlexible<*>> {
|
private fun FilterList.toItems(): List<IFlexible<*>> {
|
||||||
return mapNotNull {
|
return mapNotNull { filter ->
|
||||||
when (it) {
|
when (filter) {
|
||||||
is Filter.Header -> HeaderItem(it)
|
is Filter.Header -> HeaderItem(filter)
|
||||||
is Filter.Separator -> SeparatorItem(it)
|
is Filter.Separator -> SeparatorItem(filter)
|
||||||
is Filter.CheckBox -> CheckboxItem(it)
|
is Filter.CheckBox -> CheckboxItem(filter)
|
||||||
is Filter.TriState -> TriStateItem(it)
|
is Filter.TriState -> TriStateItem(filter)
|
||||||
is Filter.Text -> TextItem(it)
|
is Filter.Text -> TextItem(filter)
|
||||||
is Filter.Select<*> -> SelectItem(it)
|
is Filter.Select<*> -> SelectItem(filter)
|
||||||
is Filter.Group<*> -> {
|
is Filter.Group<*> -> {
|
||||||
val group = GroupItem(it)
|
val group = GroupItem(filter)
|
||||||
val subItems = it.state.mapNotNull {
|
val subItems = filter.state.mapNotNull {
|
||||||
when (it) {
|
when (it) {
|
||||||
is Filter.CheckBox -> CheckboxSectionItem(it)
|
is Filter.CheckBox -> CheckboxSectionItem(it)
|
||||||
is Filter.TriState -> TriStateSectionItem(it)
|
is Filter.TriState -> TriStateSectionItem(it)
|
||||||
@ -316,8 +316,8 @@ open class BrowseSourcePresenter(
|
|||||||
group
|
group
|
||||||
}
|
}
|
||||||
is Filter.Sort -> {
|
is Filter.Sort -> {
|
||||||
val group = SortGroup(it)
|
val group = SortGroup(filter)
|
||||||
val subItems = it.values.map {
|
val subItems = filter.values.map {
|
||||||
SortItem(it, group)
|
SortItem(it, group)
|
||||||
}
|
}
|
||||||
group.subItems = subItems
|
group.subItems = subItems
|
||||||
|
@ -43,6 +43,10 @@ class ProgressItem : AbstractFlexibleItem<ProgressItem.Holder>() {
|
|||||||
return this === other
|
return this === other
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return loadMore.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
|
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
|
||||||
|
|
||||||
val progressBar: ProgressBar = view.findViewById(R.id.progress_bar)
|
val progressBar: ProgressBar = view.findViewById(R.id.progress_bar)
|
||||||
|
@ -163,9 +163,9 @@ open class GlobalSearchPresenter(
|
|||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.onErrorReturn { MangasPage(emptyList(), false) } // Ignore timeouts or other exceptions
|
.onErrorReturn { MangasPage(emptyList(), false) } // Ignore timeouts or other exceptions
|
||||||
.map { it.mangas.take(10) } // Get at most 10 manga from search result.
|
.map { it.mangas.take(10) } // Get at most 10 manga from search result.
|
||||||
.map { it.map { networkToLocalManga(it, source.id) } } // Convert to local manga.
|
.map { list -> list.map { networkToLocalManga(it, source.id) } } // Convert to local manga.
|
||||||
.doOnNext { fetchImage(it, source) } // Load manga covers.
|
.doOnNext { fetchImage(it, source) } // Load manga covers.
|
||||||
.map { createCatalogueSearchItem(source, it.map { GlobalSearchCardItem(it) }) }
|
.map { list -> createCatalogueSearchItem(source, list.map { GlobalSearchCardItem(it) }) }
|
||||||
}, 5)
|
}, 5)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
// Update matching source with the obtained results
|
// Update matching source with the obtained results
|
||||||
@ -198,9 +198,9 @@ open class GlobalSearchPresenter(
|
|||||||
private fun initializeFetchImageSubscription() {
|
private fun initializeFetchImageSubscription() {
|
||||||
fetchImageSubscription?.unsubscribe()
|
fetchImageSubscription?.unsubscribe()
|
||||||
fetchImageSubscription = fetchImageSubject.observeOn(Schedulers.io())
|
fetchImageSubscription = fetchImageSubject.observeOn(Schedulers.io())
|
||||||
.flatMap {
|
.flatMap { pair ->
|
||||||
val source = it.second
|
val source = pair.second
|
||||||
Observable.from(it.first).filter { it.thumbnail_url == null && !it.initialized }
|
Observable.from(pair.first).filter { it.thumbnail_url == null && !it.initialized }
|
||||||
.map { Pair(it, source) }
|
.map { Pair(it, source) }
|
||||||
.concatMap { getMangaDetailsObservable(it.first, it.second) }
|
.concatMap { getMangaDetailsObservable(it.first, it.second) }
|
||||||
.map { Pair(source as CatalogueSource, it) }
|
.map { Pair(source as CatalogueSource, it) }
|
||||||
|
@ -123,11 +123,11 @@ object ChapterRecognition {
|
|||||||
if (alpha.contains("special"))
|
if (alpha.contains("special"))
|
||||||
return .97f
|
return .97f
|
||||||
|
|
||||||
if (alpha[0] == '.') {
|
return if (alpha[0] == '.') {
|
||||||
// Take value after (.)
|
// Take value after (.)
|
||||||
return parseAlphaPostFix(alpha[1])
|
parseAlphaPostFix(alpha[1])
|
||||||
} else {
|
} else {
|
||||||
return parseAlphaPostFix(alpha[0])
|
parseAlphaPostFix(alpha[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ object DiskUtil {
|
|||||||
*/
|
*/
|
||||||
fun buildValidFilename(origName: String): String {
|
fun buildValidFilename(origName: String): String {
|
||||||
val name = origName.trim('.', ' ')
|
val name = origName.trim('.', ' ')
|
||||||
if (name.isNullOrEmpty()) {
|
if (name.isEmpty()) {
|
||||||
return "(invalid)"
|
return "(invalid)"
|
||||||
}
|
}
|
||||||
val sb = StringBuilder(name.length)
|
val sb = StringBuilder(name.length)
|
||||||
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.widget
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
@ -77,6 +76,6 @@ class EmptyView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||||||
|
|
||||||
data class Action(
|
data class Action(
|
||||||
@StringRes val resId: Int,
|
@StringRes val resId: Int,
|
||||||
val listener: View.OnClickListener
|
val listener: OnClickListener
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.widget
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -160,7 +159,7 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
*/
|
*/
|
||||||
abstract inner class Adapter(private val items: List<Item>) : RecyclerView.Adapter<Holder>() {
|
abstract inner class Adapter(private val items: List<Item>) : RecyclerView.Adapter<Holder>() {
|
||||||
|
|
||||||
private val onClick = View.OnClickListener {
|
private val onClick = OnClickListener {
|
||||||
val pos = recycler.getChildAdapterPosition(it)
|
val pos = recycler.getChildAdapterPosition(it)
|
||||||
val item = items[pos]
|
val item = items[pos]
|
||||||
onItemClicked(item)
|
onItemClicked(item)
|
||||||
|
@ -76,7 +76,7 @@ open class SimpleNavigationView @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Clickable view holder.
|
* Clickable view holder.
|
||||||
*/
|
*/
|
||||||
abstract class ClickableHolder(view: View, listener: View.OnClickListener?) : Holder(view) {
|
abstract class ClickableHolder(view: View, listener: OnClickListener?) : Holder(view) {
|
||||||
init {
|
init {
|
||||||
itemView.setOnClickListener(listener)
|
itemView.setOnClickListener(listener)
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ open class SimpleNavigationView @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Radio view holder.
|
* Radio view holder.
|
||||||
*/
|
*/
|
||||||
class RadioHolder(parent: ViewGroup, listener: View.OnClickListener?) :
|
class RadioHolder(parent: ViewGroup, listener: OnClickListener?) :
|
||||||
ClickableHolder(parent.inflate(TR.layout.navigation_view_radio), listener) {
|
ClickableHolder(parent.inflate(TR.layout.navigation_view_radio), listener) {
|
||||||
|
|
||||||
val radio: RadioButton = itemView.findViewById(TR.id.nav_view_item)
|
val radio: RadioButton = itemView.findViewById(TR.id.nav_view_item)
|
||||||
@ -94,7 +94,7 @@ open class SimpleNavigationView @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Checkbox view holder.
|
* Checkbox view holder.
|
||||||
*/
|
*/
|
||||||
class CheckboxHolder(parent: ViewGroup, listener: View.OnClickListener?) :
|
class CheckboxHolder(parent: ViewGroup, listener: OnClickListener?) :
|
||||||
ClickableHolder(parent.inflate(TR.layout.navigation_view_checkbox), listener) {
|
ClickableHolder(parent.inflate(TR.layout.navigation_view_checkbox), listener) {
|
||||||
|
|
||||||
val check: CheckBox = itemView.findViewById(TR.id.nav_view_item)
|
val check: CheckBox = itemView.findViewById(TR.id.nav_view_item)
|
||||||
@ -103,7 +103,7 @@ open class SimpleNavigationView @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Multi state view holder.
|
* Multi state view holder.
|
||||||
*/
|
*/
|
||||||
class MultiStateHolder(parent: ViewGroup, listener: View.OnClickListener?) :
|
class MultiStateHolder(parent: ViewGroup, listener: OnClickListener?) :
|
||||||
ClickableHolder(parent.inflate(TR.layout.navigation_view_checkedtext), listener) {
|
ClickableHolder(parent.inflate(TR.layout.navigation_view_checkedtext), listener) {
|
||||||
|
|
||||||
val text: CheckedTextView = itemView.findViewById(TR.id.nav_view_item)
|
val text: CheckedTextView = itemView.findViewById(TR.id.nav_view_item)
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height"
|
android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:tint="?android:attr/textColorPrimary"
|
app:srcCompat="@drawable/ic_reorder_grey_24dp"
|
||||||
app:srcCompat="@drawable/ic_reorder_grey_24dp" />
|
app:tint="?android:attr/textColorPrimary" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -13,7 +12,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/colorAccent"
|
android:background="?attr/colorAccent"
|
||||||
android:elevation="5dp"
|
android:elevation="5dp"
|
||||||
android:visibility="invisible"/>
|
android:visibility="invisible" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout
|
<eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout
|
||||||
android:id="@+id/swipe_refresh"
|
android:id="@+id/swipe_refresh"
|
||||||
@ -28,9 +27,9 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:paddingBottom="@dimen/fab_list_padding"
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:descendantFocusability="blocksDescendants"
|
android:descendantFocusability="blocksDescendants"
|
||||||
|
android:paddingBottom="@dimen/fab_list_padding"
|
||||||
tools:listitem="@layout/chapters_item" />
|
tools:listitem="@layout/chapters_item" />
|
||||||
|
|
||||||
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
||||||
@ -42,7 +41,7 @@
|
|||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
app:fastScrollerBubbleEnabled="false"
|
app:fastScrollerBubbleEnabled="false"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ActionToolbar
|
<eu.kanade.tachiyomi.widget.ActionToolbar
|
||||||
android:id="@+id/action_toolbar"
|
android:id="@+id/action_toolbar"
|
||||||
@ -54,7 +53,7 @@
|
|||||||
android:id="@+id/fab"
|
android:id="@+id/fab"
|
||||||
style="@style/Theme.Widget.FAB"
|
style="@style/Theme.Widget.FAB"
|
||||||
android:text="@string/action_resume"
|
android:text="@string/action_resume"
|
||||||
app:layout_anchor="@id/recycler"
|
app:icon="@drawable/ic_play_arrow_24dp"
|
||||||
app:icon="@drawable/ic_play_arrow_24dp" />
|
app:layout_anchor="@id/recycler" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||||
android:background="@drawable/list_item_selector"
|
android:background="@drawable/list_item_selector"
|
||||||
android:paddingEnd="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingStart="16dp">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/chapter_title"
|
android:id="@+id/chapter_title"
|
||||||
@ -29,8 +29,8 @@
|
|||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/download_text"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/download_text"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:text="22/02/2016 • Scanlator • Page: 45" />
|
tools:text="22/02/2016 • Scanlator • Page: 45" />
|
||||||
|
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
|
android:elevation="2dp"
|
||||||
android:theme="?attr/actionBarTheme"
|
android:theme="?attr/actionBarTheme"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:elevation="2dp"
|
app:contentInsetEnd="8dp"
|
||||||
app:contentInsetStart="8dp"
|
app:contentInsetStart="8dp">
|
||||||
app:contentInsetEnd="8dp">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.ActionMenuView
|
<androidx.appcompat.widget.ActionMenuView
|
||||||
android:id="@+id/common_action_menu"
|
android:id="@+id/common_action_menu"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout 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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/nnf_item_container"
|
android:id="@+id/nnf_item_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -18,8 +19,8 @@
|
|||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/nnf_ic_file_folder"
|
android:src="@drawable/nnf_ic_file_folder"
|
||||||
android:tint="?attr/colorAccent"
|
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
|
app:tint="?attr/colorAccent"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:tint="?android:attr/textColorPrimary"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:srcCompat="@drawable/ic_reorder_grey_24dp" />
|
app:srcCompat="@drawable/ic_reorder_grey_24dp"
|
||||||
|
app:tint="?android:attr/textColorPrimary" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/manga_full_title"
|
android:id="@+id/manga_full_title"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
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="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@ -25,6 +25,6 @@
|
|||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
app:fastScrollerBubbleEnabled="false"
|
app:fastScrollerBubbleEnabled="false"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
@ -80,8 +80,8 @@
|
|||||||
style="@style/TextAppearance.Medium.Title"
|
style="@style/TextAppearance.Medium.Title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
android:text="@string/manga_info_full_title_label"
|
android:text="@string/manga_info_full_title_label"
|
||||||
android:textIsSelectable="false"
|
android:textIsSelectable="false"
|
||||||
app:autoSizeMaxTextSize="20sp"
|
app:autoSizeMaxTextSize="20sp"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/listPreferredItemHeightSmall"
|
android:layout_height="?attr/listPreferredItemHeightSmall"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:paddingStart="?attr/listPreferredItemPaddingStart"
|
android:paddingStart="?attr/listPreferredItemPaddingStart"
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:baselineAligned="false"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:paddingStart="?attr/listPreferredItemPaddingStart"
|
android:paddingStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:paddingEnd="?attr/listPreferredItemPaddingEnd">
|
android:paddingEnd="?attr/listPreferredItemPaddingEnd">
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="@dimen/dialog_content_padding"
|
android:paddingStart="@dimen/dialog_content_padding"
|
||||||
android:paddingTop="@dimen/dialog_margin_top_content"
|
android:paddingTop="@dimen/dialog_margin_top_content"
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:tint="@color/md_white_1000_54"
|
app:srcCompat="@drawable/ic_photo_24dp"
|
||||||
app:srcCompat="@drawable/ic_photo_24dp" />
|
app:tint="@color/md_white_1000_54" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -44,8 +44,8 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:tint="@color/md_white_1000_54"
|
app:srcCompat="@drawable/ic_share_24dp"
|
||||||
app:srcCompat="@drawable/ic_share_24dp" />
|
app:tint="@color/md_white_1000_54" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -69,8 +69,8 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:tint="@color/md_white_1000_54"
|
app:srcCompat="@drawable/ic_file_download_black_24dp"
|
||||||
app:srcCompat="@drawable/ic_file_download_black_24dp" />
|
app:tint="@color/md_white_1000_54" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -260,9 +260,9 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/pref_webtoon_side_padding"
|
android:text="@string/pref_webtoon_side_padding"
|
||||||
|
app:layout_constraintBaseline_toBaselineOf="@id/webtoon_side_padding"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toLeftOf="@id/verticalcenter"
|
app:layout_constraintRight_toLeftOf="@id/verticalcenter" />
|
||||||
app:layout_constraintBaseline_toBaselineOf="@id/webtoon_side_padding"/>
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatSpinner
|
<androidx.appcompat.widget.AppCompatSpinner
|
||||||
android:id="@+id/webtoon_side_padding"
|
android:id="@+id/webtoon_side_padding"
|
||||||
@ -272,7 +272,7 @@
|
|||||||
android:entries="@array/webtoon_side_padding"
|
android:entries="@array/webtoon_side_padding"
|
||||||
app:layout_constraintLeft_toRightOf="@id/verticalcenter"
|
app:layout_constraintLeft_toRightOf="@id/verticalcenter"
|
||||||
app:layout_constraintRight_toRightOf="@id/spinner_end"
|
app:layout_constraintRight_toRightOf="@id/spinner_end"
|
||||||
app:layout_constraintTop_toBottomOf="@id/crop_borders_webtoon"/>
|
app:layout_constraintTop_toBottomOf="@id/crop_borders_webtoon" />
|
||||||
|
|
||||||
<!-- Groups of preferences -->
|
<!-- Groups of preferences -->
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@
|
|||||||
android:alpha="0.5"
|
android:alpha="0.5"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/ic_drag_pill_24dp"
|
android:src="@drawable/ic_drag_pill_24dp"
|
||||||
android:tint="?attr/colorOnBackground"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:tint="?attr/colorOnBackground" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/reset_btn"
|
android:id="@+id/reset_btn"
|
||||||
|
@ -98,6 +98,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="@font/ptsans_narrow_bold"
|
||||||
android:lineSpacingExtra="-4dp"
|
android:lineSpacingExtra="-4dp"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
@ -105,7 +106,6 @@
|
|||||||
android:shadowDx="0"
|
android:shadowDx="0"
|
||||||
android:shadowDy="0"
|
android:shadowDy="0"
|
||||||
android:shadowRadius="4"
|
android:shadowRadius="4"
|
||||||
android:fontFamily="@font/ptsans_narrow_bold"
|
|
||||||
tools:text="Sample name" />
|
tools:text="Sample name" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
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">
|
||||||
|
|
||||||
@ -18,6 +18,6 @@
|
|||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
app:fastScrollerBubbleEnabled="false"
|
app:fastScrollerBubbleEnabled="false"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
android:id="@+id/recycler"
|
android:id="@+id/recycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
android:descendantFocusability="blocksDescendants"
|
android:descendantFocusability="blocksDescendants"
|
||||||
android:paddingBottom="?attr/actionBarSize"
|
android:paddingBottom="?attr/actionBarSize"
|
||||||
android:clipToPadding="false"
|
|
||||||
tools:listitem="@layout/updates_item" />
|
tools:listitem="@layout/updates_item" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ActionToolbar
|
<eu.kanade.tachiyomi.widget.ActionToolbar
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/material_component_lists_two_line_height"
|
android:layout_height="@dimen/material_component_lists_two_line_height"
|
||||||
android:paddingEnd="16dp"
|
android:background="@drawable/list_item_selector"
|
||||||
android:background="@drawable/list_item_selector">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/manga_cover"
|
android:id="@+id/manga_cover"
|
||||||
|
@ -40,7 +40,7 @@ import uy.kohesive.injekt.api.addSingleton
|
|||||||
* Test class for the [BackupManager].
|
* Test class for the [BackupManager].
|
||||||
* Note that this does not include the backup create/restore services.
|
* Note that this does not include the backup create/restore services.
|
||||||
*/
|
*/
|
||||||
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
|
@Config(constants = BuildConfig::class, sdk = [Build.VERSION_CODES.LOLLIPOP])
|
||||||
@RunWith(CustomRobolectricGradleTestRunner::class)
|
@RunWith(CustomRobolectricGradleTestRunner::class)
|
||||||
class BackupTest {
|
class BackupTest {
|
||||||
// Create root object
|
// Create root object
|
||||||
|
@ -72,7 +72,7 @@ class CategoryTest {
|
|||||||
|
|
||||||
// It should not have 0 as id
|
// It should not have 0 as id
|
||||||
val c = db.getCategories().executeAsBlocking()[0]
|
val c = db.getCategories().executeAsBlocking()[0]
|
||||||
assertThat(c.id).isNotZero()
|
assertThat(c.id).isNotZero
|
||||||
|
|
||||||
// Add a manga to a category
|
// Add a manga to a category
|
||||||
val m = db.getMangas().executeAsBlocking()[0]
|
val m = db.getMangas().executeAsBlocking()[0]
|
||||||
|
Loading…
Reference in New Issue
Block a user