Browse Source

Show manga with no installed source. Based on PR #1345

inorichi 6 years ago
parent
commit
3d1afe7cf2

+ 4 - 3
app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt

@@ -33,7 +33,8 @@ import timber.log.Timber
 import uy.kohesive.injekt.injectLazy
 import java.io.File
 import java.text.SimpleDateFormat
-import java.util.*
+import java.util.Date
+import java.util.Locale
 import java.util.concurrent.ExecutorService
 import java.util.concurrent.Executors
 
@@ -295,7 +296,7 @@ class BackupRestoreService : Service() {
                                           categories: List<String>, history: List<DHistory>,
                                           tracks: List<Track>): Observable<Manga>? {
         // Get source
-        val source = backupManager.sourceManager.get(manga.source) ?: return null
+        val source = backupManager.sourceManager.getOrStub(manga.source)
         val dbManga = backupManager.getMangaFromDatabase(manga)
 
         return if (dbManga == null) {
@@ -441,4 +442,4 @@ class BackupRestoreService : Service() {
         sendLocalBroadcast(intent)
     }
 
-}
+}

+ 40 - 1
app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt

@@ -1,17 +1,24 @@
 package eu.kanade.tachiyomi.source
 
 import android.content.Context
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.source.model.Page
+import eu.kanade.tachiyomi.source.model.SChapter
+import eu.kanade.tachiyomi.source.model.SManga
 import eu.kanade.tachiyomi.source.online.HttpSource
 import eu.kanade.tachiyomi.source.online.english.*
 import eu.kanade.tachiyomi.source.online.german.WieManga
 import eu.kanade.tachiyomi.source.online.russian.Mangachan
 import eu.kanade.tachiyomi.source.online.russian.Mintmanga
 import eu.kanade.tachiyomi.source.online.russian.Readmanga
+import rx.Observable
 
 open class SourceManager(private val context: Context) {
 
     private val sourcesMap = mutableMapOf<Long, Source>()
 
+    private val stubSourcesMap = mutableMapOf<Long, StubSource>()
+
     init {
         createInternalSources().forEach { registerSource(it) }
     }
@@ -20,13 +27,19 @@ open class SourceManager(private val context: Context) {
         return sourcesMap[sourceKey]
     }
 
+    fun getOrStub(sourceKey: Long): Source {
+        return sourcesMap[sourceKey] ?: stubSourcesMap.getOrPut(sourceKey) {
+            StubSource(sourceKey)
+        }
+    }
+
     fun getOnlineSources() = sourcesMap.values.filterIsInstance<HttpSource>()
 
     fun getCatalogueSources() = sourcesMap.values.filterIsInstance<CatalogueSource>()
 
     internal fun registerSource(source: Source, overwrite: Boolean = false) {
         if (overwrite || !sourcesMap.containsKey(source.id)) {
-            sourcesMap.put(source.id, source)
+            sourcesMap[source.id] = source
         }
     }
 
@@ -47,4 +60,30 @@ open class SourceManager(private val context: Context) {
             Mangasee(),
             WieManga()
     )
+
+    private inner class StubSource(override val id: Long) : Source {
+
+        override val name: String
+            get() = id.toString()
+
+        override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
+            return Observable.error(getSourceNotInstalledException())
+        }
+
+        override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
+            return Observable.error(getSourceNotInstalledException())
+        }
+
+        override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
+            return Observable.error(getSourceNotInstalledException())
+        }
+
+        override fun toString(): String {
+            return name
+        }
+
+        private fun getSourceNotInstalledException(): Exception {
+            return Exception(context.getString(R.string.source_not_installed, id.toString()))
+        }
+    }
 }

+ 5 - 6
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -25,7 +25,9 @@ import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 import java.io.IOException
 import java.io.InputStream
-import java.util.*
+import java.util.ArrayList
+import java.util.Collections
+import java.util.Comparator
 
 /**
  * Class containing library information.
@@ -113,9 +115,6 @@ class LibraryPresenter(
         val filterCompleted = preferences.filterCompleted().getOrDefault()
 
         val filterFn: (LibraryItem) -> Boolean = f@ { item ->
-            // Filter out manga without source.
-            sourceManager.get(item.manga.source) ?: return@f false
-
             // Filter when there isn't unread chapters.
             if (filterUnread && item.manga.unread == 0) {
                 return@f false
@@ -197,8 +196,8 @@ class LibraryPresenter(
                     manga1TotalChapter.compareTo(mange2TotalChapter)
                 }
                 LibrarySort.SOURCE -> {
-                    val source1Name = sourceManager.get(i1.manga.source)?.name ?: ""
-                    val source2Name = sourceManager.get(i2.manga.source)?.name ?: ""
+                    val source1Name = sourceManager.getOrStub(i1.manga.source).name
+                    val source2Name = sourceManager.getOrStub(i2.manga.source).name
                     source1Name.compareTo(source2Name)
                 }
                 else -> throw Exception("Unknown sorting mode")

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt

@@ -34,7 +34,7 @@ import kotlinx.android.synthetic.main.manga_controller.*
 import rx.Subscription
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
-import java.util.*
+import java.util.Date
 
 class MangaController : RxController, TabbedController {
 
@@ -44,7 +44,7 @@ class MangaController : RxController, TabbedController {
     }) {
         this.manga = manga
         if (manga != null) {
-            source = Injekt.get<SourceManager>().get(manga.source)
+            source = Injekt.get<SourceManager>().getOrStub(manga.source)
         }
     }
 

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationPresenter.kt

@@ -71,7 +71,7 @@ class MigrationPresenter(
     private fun findSourcesWithManga(library: List<Manga>): List<SourceItem> {
         val header = SelectionHeader()
         return library.map { it.source }.toSet()
-                .mapNotNull { if (it != LocalSource.ID) sourceManager.get(it) else null }
+                .mapNotNull { if (it != LocalSource.ID) sourceManager.getOrStub(it) else null }
                 .map { SourceItem(it, header) }
     }
 

+ 3 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -32,7 +32,8 @@ import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 import java.io.File
 import java.net.URLConnection
-import java.util.*
+import java.util.Comparator
+import java.util.Date
 
 /**
  * Presenter of [ReaderActivity].
@@ -74,7 +75,7 @@ class ReaderPresenter(
     /**
      * Source of the manga.
      */
-    private val source by lazy { sourceManager.get(manga.source)!! }
+    private val source by lazy { sourceManager.getOrStub(manga.source) }
 
     /**
      * Chapter list for the active manga. It's retrieved lazily and should be accessed for the first

+ 4 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersPresenter.kt

@@ -14,7 +14,9 @@ import rx.schedulers.Schedulers
 import timber.log.Timber
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
-import java.util.*
+import java.util.Calendar
+import java.util.Date
+import java.util.TreeMap
 
 class RecentChaptersPresenter(
         val preferences: PreferencesHelper = Injekt.get(),
@@ -57,7 +59,6 @@ class RecentChaptersPresenter(
                 .map { mangaChapters ->
                     val map = TreeMap<Date, MutableList<MangaChapter>> { d1, d2 -> d2.compareTo(d1) }
                     val byDay = mangaChapters
-                            .filter { sourceManager.get(it.manga.source) != null }
                             .groupByTo(map, { getMapKey(it.chapter.date_fetch) })
                     byDay.flatMap {
                         val dateItem = DateItem(it.key)
@@ -195,4 +196,4 @@ class RecentChaptersPresenter(
         item.download = null
     }
 
-}
+}

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadHolder.kt

@@ -7,7 +7,7 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
 import eu.kanade.tachiyomi.data.glide.GlideApp
 import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
 import kotlinx.android.synthetic.main.recently_read_item.*
-import java.util.*
+import java.util.Date
 
 /**
  * Holder that contains recent manga item
@@ -52,7 +52,7 @@ class RecentlyReadHolder(
         // Set source + chapter title
         val formattedNumber = adapter.decimalFormat.format(chapter.chapter_number.toDouble())
         manga_source.text = itemView.context.getString(R.string.recent_manga_source)
-                .format(adapter.sourceManager.get(manga.source)?.toString(), formattedNumber)
+                .format(adapter.sourceManager.getOrStub(manga.source).toString(), formattedNumber)
 
         // Set last read timestamp title
         last_read.text = adapter.dateFormat.format(Date(history.last_read))

+ 4 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadPresenter.kt

@@ -5,12 +5,13 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.History
 import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
 import uy.kohesive.injekt.injectLazy
-import java.util.*
+import java.util.Calendar
+import java.util.Comparator
+import java.util.Date
 
 /**
  * Presenter of RecentlyReadFragment.
@@ -24,8 +25,6 @@ class RecentlyReadPresenter : BasePresenter<RecentlyReadController>() {
      */
     val db: DatabaseHelper by injectLazy()
 
-    private val sourceManager: SourceManager by injectLazy()
-
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
 
@@ -45,10 +44,7 @@ class RecentlyReadPresenter : BasePresenter<RecentlyReadController>() {
         cal.add(Calendar.MONTH, -1)
 
         return db.getRecentManga(cal.time).asRxObservable()
-                .map { recents ->
-                    recents.filter { sourceManager.get(it.manga.source) != null }
-                            .map(::RecentlyReadItem)
-                }
+                .map { recents -> recents.map(::RecentlyReadItem) }
                 .observeOn(AndroidSchedulers.mainThread())
     }
 

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -349,6 +349,7 @@
     <string name="icon_creation_fail">Failed to create shortcut!</string>
     <string name="delete_downloads_for_manga">Delete downloaded chapters?</string>
     <string name="copied_to_clipboard">%1$s copied to clipboard</string>
+    <string name="source_not_installed">Source not installed: %1$s</string>
 
     <!-- Manga chapters fragment -->
     <string name="manga_chapters_tab">Chapters</string>

+ 1 - 1
build.gradle

@@ -7,7 +7,7 @@ buildscript {
         google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.1.2'
+        classpath 'com.android.tools.build:gradle:3.1.3'
         classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'
         classpath 'com.github.zellius:android-shortcut-gradle-plugin:0.1.2'
         classpath 'com.google.gms:google-services:3.2.0'