mirror of
https://github.com/mihonapp/mihon.git
synced 2025-08-18 04:21:32 +02: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:
app
build.gradle
src
main
AndroidManifest.xml
java
eu
kanade
tachiyomi
data
backup
cache
database
resolvers
download
glide
library
track
extension
source
ui
base
holder
extension
library
manga
chapter
info
track
migration
more
reader
recent
setting
source
util
widget
res
layout
categories_item.xmlchapters_controller.xmlchapters_item.xmlcommon_action_toolbar.xmlcommon_listitem_dir.xmldownload_item.xmlextension_controller.xmlmanga_info_controller.xmlnavigation_view_spinner.xmlnavigation_view_text.xmlpref_library_columns.xmlreader_page_sheet.xmlreader_settings_sheet.xmlsource_filter_sheet.xmlsource_grid_item.xmlsource_main_controller.xmlupdates_controller.xmlupdates_item.xml
test
java
eu
kanade
tachiyomi
data
@@ -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]
|
||||||
|
Reference in New Issue
Block a user