From 365a60c0dfaf431a2e36d0cfd8685bc87b50016b Mon Sep 17 00:00:00 2001 From: Carlos Date: Thu, 11 Apr 2019 20:18:41 -0400 Subject: [PATCH] clean up mangadex some remove some strings unused remove catalog view add captcha option when logging in --- app/shortcuts.xml | 8 +- .../java/eu/kanade/tachiyomi/AppModule.kt | 2 +- .../data/backup/BackupRestoreService.kt | 2 +- .../tachiyomi/data/download/DownloadCache.kt | 2 +- .../data/preference/PreferenceKeys.kt | 4 +- .../data/preference/PreferencesHelper.kt | 3 + .../kanade/tachiyomi/network/NetworkHelper.kt | 29 ++- .../tachiyomi/source/ConfigurableSource.kt | 8 - .../kanade/tachiyomi/source/SourceFactory.kt | 12 - .../kanade/tachiyomi/source/SourceManager.kt | 64 +---- .../source/online/english/Mangadex.kt | 50 +--- .../ui/catalogue/CatalogueAdapter.kt | 48 ---- .../ui/catalogue/CatalogueController.kt | 236 ------------------ .../ui/catalogue/CataloguePresenter.kt | 102 -------- .../tachiyomi/ui/catalogue/LangHolder.kt | 15 -- .../kanade/tachiyomi/ui/catalogue/LangItem.kt | 38 --- .../catalogue/SourceDividerItemDecoration.kt | 44 ---- .../tachiyomi/ui/catalogue/SourceHolder.kt | 60 ----- .../tachiyomi/ui/catalogue/SourceItem.kt | 41 --- .../browse/BrowseCatalogueController.kt | 5 +- .../browse/BrowseCataloguePresenter.kt | 4 +- .../global_search/CatalogueSearchAdapter.kt | 74 ------ .../CatalogueSearchCardAdapter.kt | 28 --- .../CatalogueSearchCardHolder.kt | 52 ---- .../global_search/CatalogueSearchCardItem.kt | 35 --- .../CatalogueSearchController.kt | 188 -------------- .../global_search/CatalogueSearchHolder.kt | 99 -------- .../global_search/CatalogueSearchItem.kt | 66 ----- .../global_search/CatalogueSearchPresenter.kt | 222 ---------------- .../tachiyomi/ui/library/LibraryPresenter.kt | 4 +- .../kanade/tachiyomi/ui/main/MainActivity.kt | 47 +++- .../tachiyomi/ui/manga/MangaController.kt | 2 +- .../ui/manga/info/MangaInfoController.kt | 27 +- .../tachiyomi/ui/reader/ReaderPresenter.kt | 2 +- .../ui/recently_read/RecentlyReadHolder.kt | 2 +- .../ui/setting/SettingsMainController.kt | 6 + .../ui/setting/SettingsSiteController.kt | 54 ++++ .../ui/setting/SettingsSourcesController.kt | 118 --------- .../preference/LoginDialogPreference.kt | 18 ++ .../res/drawable/ic_new_box_black_24dp.xml | 9 + .../main/res/layout/pref_account_login.xml | 9 + app/src/main/res/menu/catalogue_main.xml | 4 - app/src/main/res/menu/menu_navigation.xml | 5 +- app/src/main/res/values/strings.xml | 18 +- 44 files changed, 216 insertions(+), 1650 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueController.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangHolder.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangItem.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceDividerItemDecoration.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceHolder.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceItem.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchAdapter.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardAdapter.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardHolder.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardItem.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchHolder.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchItem.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchPresenter.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSiteController.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSourcesController.kt create mode 100644 app/src/main/res/drawable/ic_new_box_black_24dp.xml diff --git a/app/shortcuts.xml b/app/shortcuts.xml index f0d74789ea..d4154d6868 100644 --- a/app/shortcuts.xml +++ b/app/shortcuts.xml @@ -37,11 +37,11 @@ android:enabled="true" android:icon="@drawable/sc_explore_48dp" android:shortcutDisabledMessage="@string/app_not_available" - android:shortcutId="show_catalogues" - android:shortcutLongLabel="@string/label_catalogues" - android:shortcutShortLabel="@string/label_catalogues"> + android:shortcutId="show_browse" + android:shortcutLongLabel="@string/label_browse" + android:shortcutShortLabel="@string/label_browse"> diff --git a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt index dea899f456..b8920ed139 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt @@ -30,7 +30,7 @@ class AppModule(val app: Application) : InjektModule { addSingletonFactory { NetworkHelper(app) } - addSingletonFactory { SourceManager(app) } + addSingletonFactory { SourceManager() } addSingletonFactory { DownloadManager(app) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt index db6866e289..487ea07c3d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt @@ -296,7 +296,7 @@ class BackupRestoreService : Service() { categories: List, history: List, tracks: List): Observable? { // Get source - val source = backupManager.sourceManager.getOrStub(manga.source) + val source = backupManager.sourceManager.getSource(manga.source) val dbManga = backupManager.getMangaFromDatabase(manga) return if (dbManga == null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt index bc6d6b42ee..55e9f111e4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt @@ -121,7 +121,7 @@ class DownloadCache( * Renews the downloads cache. */ private fun renew() { - val onlineSources = sourceManager.getOnlineSources() + val onlineSources = sourceManager.getSources() val sourceDirs = rootDir.dir.listFiles() .orEmpty() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 1b2e6bb322..16308ac3c0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -111,10 +111,10 @@ object PreferenceKeys { const val downloadBadge = "display_download_badge" - @Deprecated("Use the preferences of the source") + const val showR18 = "show_r18" + fun sourceUsername(sourceId: Long) = "pref_source_username_$sourceId" - @Deprecated("Use the preferences of the source") fun sourcePassword(sourceId: Long) = "pref_source_password_$sourceId" fun sourceSharedPref(sourceId: Long) = "source_$sourceId" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 58ad2b0aff..0a1136ee49 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -43,6 +43,9 @@ class PreferencesHelper(val context: Context) { fun showPageNumber() = rxPrefs.getBoolean(Keys.showPageNumber, true) + fun r18() = prefs.getInt(Keys.showR18, 0) + + fun trueColor() = rxPrefs.getBoolean(Keys.trueColor, false) fun fullscreen() = rxPrefs.getBoolean(Keys.fullscreen, true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt index 217eb45fa5..4e7bcf7243 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -1,8 +1,10 @@ package eu.kanade.tachiyomi.network import android.content.Context +import eu.kanade.tachiyomi.BuildConfig import okhttp3.Cache import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import java.io.File class NetworkHelper(context: Context) { @@ -13,13 +15,22 @@ class NetworkHelper(context: Context) { val cookieManager = AndroidCookieJar() - val client = OkHttpClient.Builder() - .cookieJar(cookieManager) - .cache(Cache(cacheDir, cacheSize)) - .build() + val client = + if(BuildConfig.DEBUG) { + OkHttpClient.Builder() + .cookieJar(cookieManager) + .cache(Cache(cacheDir, cacheSize)) + .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) + .build() + }else { + OkHttpClient.Builder() + .cookieJar(cookieManager) + .cache(Cache(cacheDir, cacheSize)) + .build() + } + + val cloudflareClient = client.newBuilder() + .addInterceptor(CloudflareInterceptor(context)) + .build() + } - val cloudflareClient = client.newBuilder() - .addInterceptor(CloudflareInterceptor(context)) - .build() - -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt deleted file mode 100644 index 6b3f99aceb..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt +++ /dev/null @@ -1,8 +0,0 @@ -package eu.kanade.tachiyomi.source - -import android.support.v7.preference.PreferenceScreen - -interface ConfigurableSource : Source { - - fun setupPreferenceScreen(screen: PreferenceScreen) -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt b/app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt deleted file mode 100644 index d326c437a5..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt +++ /dev/null @@ -1,12 +0,0 @@ -package eu.kanade.tachiyomi.source - -/** - * A factory for creating sources at runtime. - */ -interface SourceFactory { - /** - * Create a new copy of the sources - * @return The created sources - */ - fun createSources(): List -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt index aa27b5eaeb..ce4bb83b14 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt @@ -1,75 +1,21 @@ 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.Mangadex -import rx.Observable -open class SourceManager(private val context: Context) { +open class SourceManager { private val sourcesMap = mutableMapOf() - private val stubSourcesMap = mutableMapOf() - init { - createInternalSources().forEach { registerSource(it) } + val source = Mangadex("en", "gb", 1) + sourcesMap[source.id] = source } open fun get(sourceKey: Long): Source? { return sourcesMap[sourceKey] } + fun getSource(sourceKey: Long): Source = sourcesMap[sourceKey]!! - fun getOrStub(sourceKey: Long): Source { - return sourcesMap[sourceKey] ?: stubSourcesMap.getOrPut(sourceKey) { - StubSource(sourceKey) - } - } - - fun getOnlineSources() = sourcesMap.values.filterIsInstance() - - fun getCatalogueSources() = sourcesMap.values.filterIsInstance() - - internal fun registerSource(source: Source, overwrite: Boolean = false) { - if (overwrite || !sourcesMap.containsKey(source.id)) { - sourcesMap[source.id] = source - } - } - - internal fun unregisterSource(source: Source) { - sourcesMap.remove(source.id) - } - - private fun createInternalSources(): List = listOf( - Mangadex("en", "gb", 1) - ) - - private inner class StubSource(override val id: Long) : Source { - - override val name: String - get() = id.toString() - - override fun fetchMangaDetails(manga: SManga): Observable { - return Observable.error(getSourceNotInstalledException()) - } + fun getSources() = sourcesMap.values.toList() - override fun fetchChapterList(manga: SManga): Observable> { - return Observable.error(getSourceNotInstalledException()) - } - - override fun fetchPageList(chapter: SChapter): Observable> { - 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())) - } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Mangadex.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Mangadex.kt index af02e7352e..33e85bd980 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Mangadex.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Mangadex.kt @@ -1,18 +1,14 @@ package eu.kanade.tachiyomi.source.online.english -import android.app.Application -import android.content.SharedPreferences -import android.support.v7.preference.ListPreference -import android.support.v7.preference.PreferenceScreen import com.github.salomonbrys.kotson.* import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.JsonParser +import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.asObservable import eu.kanade.tachiyomi.network.asObservableSuccess -import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.online.LoginSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource @@ -21,13 +17,13 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element import rx.Observable -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get +import uy.kohesive.injekt.injectLazy import java.net.URLEncoder import java.util.* import java.util.concurrent.TimeUnit +import kotlin.collections.set -open class Mangadex(override val lang: String, private val internalLang: String, private val langCode: Int) : ConfigurableSource, LoginSource, ParsedHttpSource() { +open class Mangadex(override val lang: String, private val internalLang: String, private val langCode: Int) : LoginSource, ParsedHttpSource() { override val name = "MangaDex" @@ -37,11 +33,9 @@ open class Mangadex(override val lang: String, private val internalLang: String, override val supportsLatest = true - private val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) - } + private val preferences: PreferencesHelper by injectLazy() - private fun clientBuilder(): OkHttpClient = clientBuilder(getShowR18()) + private fun clientBuilder(): OkHttpClient = clientBuilder(preferences.r18()) private fun clientBuilder(r18Toggle: Int): OkHttpClient = network.cloudflareClient.newBuilder() .connectTimeout(10, TimeUnit.SECONDS) @@ -138,7 +132,7 @@ open class Mangadex(override val lang: String, private val internalLang: String, override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { return if (query.startsWith(PREFIX_ID_SEARCH)) { val realQuery = query.removePrefix(PREFIX_ID_SEARCH) - client.newCall(searchMangaByIdRequest(realQuery)) + clientBuilder().newCall(searchMangaByIdRequest(realQuery)) .asObservableSuccess() .map { response -> val details = mangaDetailsParse(response) @@ -478,26 +472,6 @@ open class Mangadex(override val lang: String, private val internalLang: String, return baseUrl + attr } - override fun setupPreferenceScreen(screen: PreferenceScreen) { - val myPref = ListPreference(screen.context).apply { - key = SHOW_R18_PREF_Title - title = SHOW_R18_PREF_Title - - title = SHOW_R18_PREF_Title - entries = arrayOf("Show No R18+", "Show All", "Show Only R18+") - entryValues = arrayOf("0", "1", "2") - summary = "%s" - - setOnPreferenceChangeListener { _, newValue -> - val selected = newValue as String - val index = this.findIndexOfValue(selected) - preferences.edit().putInt(SHOW_R18_PREF, index).commit() - } - } - - screen.addPreference(myPref) - } - override fun isLogged(): Boolean { val httpUrl = HttpUrl.parse(baseUrl)!! return network.cookieManager.get(httpUrl).any { it.name() == "mangadex_rememberme_token" } @@ -512,7 +486,7 @@ open class Mangadex(override val lang: String, private val internalLang: String, .build() - return client.newCall(POST("$baseUrl/ajax/actions.ajax.php?function=login", headers, formBody)) + return clientBuilder().newCall(POST("$baseUrl/ajax/actions.ajax.php?function=login", headers, formBody)) .asObservable() .map { isAuthenticationSuccessful(it) } } @@ -525,8 +499,6 @@ open class Mangadex(override val lang: String, private val internalLang: String, return false } - private fun getShowR18(): Int = preferences.getInt(SHOW_R18_PREF, 0) - private class TextField(name: String, val key: String) : Filter.Text(name) private class Tag(val id: String, name: String) : Filter.TriState(name) @@ -544,7 +516,7 @@ open class Mangadex(override val lang: String, private val internalLang: String, sortables.map { it.first }.toTypedArray(), Filter.Sort.Selection(0, true)) - private class OriginalLanguage : Filter.Select("Original Language", SOURCE_LANG_LIST.map { it -> it.first }.toTypedArray()) + private class OriginalLanguage : Filter.Select("Original Language", SOURCE_LANG_LIST.map { it.first }.toTypedArray()) override fun getFilterList() = FilterList( TextField("Author", "author"), @@ -662,10 +634,6 @@ open class Mangadex(override val lang: String, private val internalLang: String, private const val ALL = 1 private const val ONLY_R18 = 2 - private const val SHOW_R18_PREF_Title = "Default R18 Setting" - private const val SHOW_R18_PREF = "showR18Default" - private const val REMEMBER_ME_TOKEN = "rememberMeToken" - private const val API_MANGA = "/api/manga/" private const val API_CHAPTER = "/api/chapter/" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.kt deleted file mode 100644 index 1b1f09d9ad..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.kt +++ /dev/null @@ -1,48 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.IFlexible -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.util.getResourceColor - -/** - * Adapter that holds the catalogue cards. - * - * @param controller instance of [CatalogueController]. - */ -class CatalogueAdapter(val controller: CatalogueController) : - FlexibleAdapter>(null, controller, true) { - - val cardBackground = controller.activity!!.getResourceColor(R.attr.background_card) - - init { - setDisplayHeadersAtStartUp(true) - } - - /** - * Listener for browse item clicks. - */ - val browseClickListener: OnBrowseClickListener = controller - - /** - * Listener for latest item clicks. - */ - val latestClickListener: OnLatestClickListener = controller - - /** - * Listener which should be called when user clicks browse. - * Note: Should only be handled by [CatalogueController] - */ - interface OnBrowseClickListener { - fun onBrowseClick(position: Int) - } - - /** - * Listener which should be called when user clicks latest. - * Note: Should only be handled by [CatalogueController] - */ - interface OnLatestClickListener { - fun onLatestClick(position: Int) - } -} - diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueController.kt deleted file mode 100644 index ceed07a35d..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueController.kt +++ /dev/null @@ -1,236 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import android.Manifest.permission.WRITE_EXTERNAL_STORAGE -import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.SearchView -import android.view.* -import com.bluelinelabs.conductor.ControllerChangeHandler -import com.bluelinelabs.conductor.ControllerChangeType -import com.bluelinelabs.conductor.RouterTransaction -import com.bluelinelabs.conductor.changehandler.FadeChangeHandler -import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.IFlexible -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.source.CatalogueSource -import eu.kanade.tachiyomi.source.online.LoginSource -import eu.kanade.tachiyomi.ui.base.controller.NucleusController -import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe -import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction -import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController -import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController -import eu.kanade.tachiyomi.ui.catalogue.latest.LatestUpdatesController -import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController -import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog -import kotlinx.android.synthetic.main.catalogue_main_controller.* -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get - -/** - * This controller shows and manages the different catalogues enabled by the user. - * This controller should only handle UI actions, IO actions should be done by [CataloguePresenter] - * [SourceLoginDialog.Listener] refreshes the adapter on successful login of catalogues. - * [CatalogueAdapter.OnBrowseClickListener] call function data on browse item click. - * [CatalogueAdapter.OnLatestClickListener] call function data on latest item click - */ -class CatalogueController : NucleusController(), - SourceLoginDialog.Listener, - FlexibleAdapter.OnItemClickListener, - CatalogueAdapter.OnBrowseClickListener, - CatalogueAdapter.OnLatestClickListener { - - /** - * Application preferences. - */ - private val preferences: PreferencesHelper = Injekt.get() - - /** - * Adapter containing sources. - */ - private var adapter: CatalogueAdapter? = null - - /** - * Called when controller is initialized. - */ - init { - // Enable the option menu - setHasOptionsMenu(true) - } - - /** - * Set the title of controller. - * - * @return title. - */ - override fun getTitle(): String? { - return applicationContext?.getString(R.string.label_catalogues) - } - - /** - * Create the [CataloguePresenter] used in controller. - * - * @return instance of [CataloguePresenter] - */ - override fun createPresenter(): CataloguePresenter { - return CataloguePresenter() - } - - /** - * Initiate the view with [R.layout.catalogue_main_controller]. - * - * @param inflater used to load the layout xml. - * @param container containing parent views. - * @return inflated view. - */ - override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { - return inflater.inflate(R.layout.catalogue_main_controller, container, false) - } - - /** - * Called when the view is created - * - * @param view view of controller - */ - override fun onViewCreated(view: View) { - super.onViewCreated(view) - - adapter = CatalogueAdapter(this) - - // Create recycler and set adapter. - recycler.layoutManager = LinearLayoutManager(view.context) - recycler.adapter = adapter - recycler.addItemDecoration(SourceDividerItemDecoration(view.context)) - - requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301) - } - - override fun onDestroyView(view: View) { - adapter = null - super.onDestroyView(view) - } - - override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { - super.onChangeStarted(handler, type) - if (!type.isPush && handler is SettingsSourcesFadeChangeHandler) { - presenter.updateSources() - } - } - - /** - * Called when login dialog is closed, refreshes the adapter. - * - * @param source clicked item containing source information. - */ - override fun loginDialogClosed(source: LoginSource) { - if (source.isLogged()) { - adapter?.clear() - presenter.loadSources() - } - } - - /** - * Called when item is clicked - */ - override fun onItemClick(position: Int): Boolean { - val item = adapter?.getItem(position) as? SourceItem ?: return false - val source = item.source - if (source is LoginSource && !source.isLogged()) { - val dialog = SourceLoginDialog(source) - dialog.targetController = this - dialog.showDialog(router) - } else { - // Open the catalogue view. - openCatalogue(source, BrowseCatalogueController(source)) - } - return false - } - - /** - * Called when browse is clicked in [CatalogueAdapter] - */ - override fun onBrowseClick(position: Int) { - onItemClick(position) - } - - /** - * Called when latest is clicked in [CatalogueAdapter] - */ - override fun onLatestClick(position: Int) { - val item = adapter?.getItem(position) as? SourceItem ?: return - openCatalogue(item.source, LatestUpdatesController(item.source)) - } - - /** - * Opens a catalogue with the given controller. - */ - private fun openCatalogue(source: CatalogueSource, controller: BrowseCatalogueController) { - preferences.lastUsedCatalogueSource().set(source.id) - router.pushController(controller.withFadeTransaction()) - } - - /** - * Adds items to the options menu. - * - * @param menu menu containing options. - * @param inflater used to load the menu xml. - */ - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - // Inflate menu - inflater.inflate(R.menu.catalogue_main, menu) - - // Initialize search option. - val searchItem = menu.findItem(R.id.action_search) - val searchView = searchItem.actionView as SearchView - - // Change hint to show global search. - searchView.queryHint = applicationContext?.getString(R.string.action_global_search_hint) - - // Create query listener which opens the global search view. - searchView.queryTextChangeEvents() - .filter { it.isSubmitted } - .subscribeUntilDestroy { performGlobalSearch(it.queryText().toString()) } - } - - fun performGlobalSearch(query: String){ - router.pushController(CatalogueSearchController(query).withFadeTransaction()) - } - - /** - * Called when an option menu item has been selected by the user. - * - * @param item The selected item. - * @return True if this event has been consumed, false if it has not. - */ - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - // Initialize option to open catalogue settings. - R.id.action_settings -> { - router.pushController((RouterTransaction.with(SettingsSourcesController())) - .popChangeHandler(SettingsSourcesFadeChangeHandler()) - .pushChangeHandler(FadeChangeHandler())) - } - else -> return super.onOptionsItemSelected(item) - } - return true - } - - /** - * Called to update adapter containing sources. - */ - fun setSources(sources: List>) { - adapter?.updateDataSet(sources) - } - - /** - * Called to set the last used catalogue at the top of the view. - */ - fun setLastUsedSource(item: SourceItem?) { - adapter?.removeAllScrollableHeaders() - if (item != null) { - adapter?.addScrollableHeader(item) - } - } - - class SettingsSourcesFadeChangeHandler : FadeChangeHandler() -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt deleted file mode 100644 index ae2a965ebf..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt +++ /dev/null @@ -1,102 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import android.os.Bundle -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.source.CatalogueSource -import eu.kanade.tachiyomi.source.SourceManager -import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter -import rx.Observable -import rx.Subscription -import rx.android.schedulers.AndroidSchedulers -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import java.util.* -import java.util.concurrent.TimeUnit - -/** - * Presenter of [CatalogueController] - * Function calls should be done from here. UI calls should be done from the controller. - * - * @param sourceManager manages the different sources. - * @param preferences application preferences. - */ -class CataloguePresenter( - val sourceManager: SourceManager = Injekt.get(), - private val preferences: PreferencesHelper = Injekt.get() -) : BasePresenter() { - - /** - * Enabled sources. - */ - var sources = getEnabledSources() - - /** - * Subscription for retrieving enabled sources. - */ - private var sourceSubscription: Subscription? = null - - override fun onCreate(savedState: Bundle?) { - super.onCreate(savedState) - - // Load enabled and last used sources - loadSources() - loadLastUsedSource() - } - - /** - * Unsubscribe and create a new subscription to fetch enabled sources. - */ - fun loadSources() { - sourceSubscription?.unsubscribe() - - val map = TreeMap> { d1, d2 -> - // Catalogues without a lang defined will be placed at the end - when { - d1 == "" && d2 != "" -> 1 - d2 == "" && d1 != "" -> -1 - else -> d1.compareTo(d2) - } - } - val byLang = sources.groupByTo(map, { it.lang }) - val sourceItems = byLang.flatMap { - val langItem = LangItem(it.key) - it.value.map { source -> SourceItem(source, langItem) } - } - - sourceSubscription = Observable.just(sourceItems) - .subscribeLatestCache(CatalogueController::setSources) - } - - private fun loadLastUsedSource() { - val sharedObs = preferences.lastUsedCatalogueSource().asObservable().share() - - // Emit the first item immediately but delay subsequent emissions by 500ms. - Observable.merge( - sharedObs.take(1), - sharedObs.skip(1).delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())) - .distinctUntilChanged() - .map { (sourceManager.get(it) as? CatalogueSource)?.let { SourceItem(it) } } - .subscribeLatestCache(CatalogueController::setLastUsedSource) - } - - fun updateSources() { - sources = getEnabledSources() - loadSources() - } - - /** - * Returns a list of enabled sources ordered by language and name. - * - * @return list containing enabled sources. - */ - private fun getEnabledSources(): List { - val languages = preferences.enabledLanguages().getOrDefault() - val hiddenCatalogues = preferences.hiddenCatalogues().getOrDefault() - - return sourceManager.getCatalogueSources() - .filter { it.lang in languages } - .filterNot { it.id.toString() in hiddenCatalogues } - .sortedBy { "(${it.lang}) ${it.name}" } - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangHolder.kt deleted file mode 100644 index 66c94967d3..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangHolder.kt +++ /dev/null @@ -1,15 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import android.view.View -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder -import eu.kanade.tachiyomi.util.LocaleHelper -import kotlinx.android.synthetic.main.catalogue_main_controller_card.* - -class LangHolder(view: View, adapter: FlexibleAdapter<*>) : - BaseFlexibleViewHolder(view, adapter) { - - fun bind(item: LangItem) { - title.text = LocaleHelper.getDisplayName(item.code, itemView.context) - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangItem.kt deleted file mode 100644 index dfa6a91d2f..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/LangItem.kt +++ /dev/null @@ -1,38 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import android.view.View -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.AbstractHeaderItem -import eu.kanade.tachiyomi.R - -/** - * Item that contains the language header. - * - * @param code The lang code. - */ -data class LangItem(val code: String) : AbstractHeaderItem() { - - /** - * Returns the layout resource of this item. - */ - override fun getLayoutRes(): Int { - return R.layout.catalogue_main_controller_card - } - - /** - * Creates a new view holder for this item. - */ - override fun createViewHolder(view: View, adapter: FlexibleAdapter<*>): LangHolder { - return LangHolder(view, adapter) - } - - /** - * Binds this item to the given view holder. - */ - override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: LangHolder, - position: Int, payloads: List?) { - - holder.bind(this) - } - -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceDividerItemDecoration.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceDividerItemDecoration.kt deleted file mode 100644 index a4c33beb75..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceDividerItemDecoration.kt +++ /dev/null @@ -1,44 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Rect -import android.graphics.drawable.Drawable -import android.support.v7.widget.RecyclerView -import android.view.View - -class SourceDividerItemDecoration(context: Context) : RecyclerView.ItemDecoration() { - - private val divider: Drawable - - init { - val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.listDivider)) - divider = a.getDrawable(0) - a.recycle() - } - - override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { - val childCount = parent.childCount - for (i in 0 until childCount - 1) { - val child = parent.getChildAt(i) - val holder = parent.getChildViewHolder(child) - if (holder is SourceHolder && - parent.getChildViewHolder(parent.getChildAt(i + 1)) is SourceHolder) { - val params = child.layoutParams as RecyclerView.LayoutParams - val top = child.bottom + params.bottomMargin - val bottom = top + divider.intrinsicHeight - val left = parent.paddingLeft + holder.margin - val right = parent.width - parent.paddingRight - holder.margin - - divider.setBounds(left, top, right, bottom) - divider.draw(c) - } - } - } - - override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, - state: RecyclerView.State) { - outRect.set(0, 0, 0, divider.intrinsicHeight) - } - -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceHolder.kt deleted file mode 100644 index 4366e6d35b..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceHolder.kt +++ /dev/null @@ -1,60 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import android.view.View -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.source.online.LoginSource -import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder -import eu.kanade.tachiyomi.ui.base.holder.SlicedHolder -import eu.kanade.tachiyomi.util.getRound -import eu.kanade.tachiyomi.util.gone -import eu.kanade.tachiyomi.util.visible -import io.github.mthli.slice.Slice -import kotlinx.android.synthetic.main.catalogue_main_controller_card_item.* - -class SourceHolder(view: View, override val adapter: CatalogueAdapter) : - BaseFlexibleViewHolder(view, adapter), - SlicedHolder { - - override val slice = Slice(card).apply { - setColor(adapter.cardBackground) - } - - override val viewToSlice: View - get() = card - - init { - source_browse.setOnClickListener { - adapter.browseClickListener.onBrowseClick(adapterPosition) - } - - source_latest.setOnClickListener { - adapter.latestClickListener.onLatestClick(adapterPosition) - } - } - - fun bind(item: SourceItem) { - val source = item.source - setCardEdges(item) - - // Set source name - title.text = source.name - - // Set circle letter image. - itemView.post { - image.setImageDrawable(image.getRound(source.name.take(1).toUpperCase(), false)) - } - - // If source is login, show only login option - if (source is LoginSource && !source.isLogged()) { - source_browse.setText(R.string.login) - source_latest.gone() - } else { - source_browse.setText(R.string.browse) - if (source.supportsLatest) { - source_latest.visible() - } else { - source_latest.gone() - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceItem.kt deleted file mode 100644 index 57c1fdf8ae..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/SourceItem.kt +++ /dev/null @@ -1,41 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue - -import android.view.View -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.AbstractSectionableItem -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.source.CatalogueSource - -/** - * Item that contains source information. - * - * @param source Instance of [CatalogueSource] containing source information. - * @param header The header for this item. - */ -data class SourceItem(val source: CatalogueSource, val header: LangItem? = null) : - AbstractSectionableItem(header) { - - /** - * Returns the layout resource of this item. - */ - override fun getLayoutRes(): Int { - return R.layout.catalogue_main_controller_card_item - } - - /** - * Creates a new view holder for this item. - */ - override fun createViewHolder(view: View, adapter: FlexibleAdapter<*>): SourceHolder { - return SourceHolder(view, adapter as CatalogueAdapter) - } - - /** - * Binds this item to the given view holder. - */ - override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: SourceHolder, - position: Int, payloads: List?) { - - holder.bind(this) - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt index 80f284204f..a54732e612 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt @@ -47,7 +47,9 @@ open class BrowseCatalogueController(bundle: Bundle) : constructor(source: CatalogueSource) : this(Bundle().apply { putLong(SOURCE_ID_KEY, source.id) - }) + putString(QUERY_NAME_KEY, "One Piece") + } + ) /** * Preferences helper. @@ -507,6 +509,7 @@ open class BrowseCatalogueController(bundle: Bundle) : protected companion object { const val SOURCE_ID_KEY = "sourceId" + const val QUERY_NAME_KEY = "queryKey" } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt index 6bc440eae6..0c5bafa5f5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt @@ -100,7 +100,7 @@ open class BrowseCataloguePresenter( sourceFilters = source.getFilterList() if (savedState != null) { - query = savedState.getString(::query.name, "") + query = savedState.getString("queryKey", "") } add(prefs.catalogueAsList().asObservable() @@ -110,7 +110,7 @@ open class BrowseCataloguePresenter( } override fun onSave(state: Bundle) { - state.putString(::query.name, query) + state.putString("queryKey", query) super.onSave(state) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchAdapter.kt deleted file mode 100644 index 0b1b822e0f..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchAdapter.kt +++ /dev/null @@ -1,74 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import android.os.Bundle -import android.os.Parcelable -import android.support.v7.widget.RecyclerView -import android.util.SparseArray -import eu.davidea.flexibleadapter.FlexibleAdapter - -/** - * Adapter that holds the search cards. - * - * @param controller instance of [CatalogueSearchController]. - */ -class CatalogueSearchAdapter(val controller: CatalogueSearchController) : - FlexibleAdapter(null, controller, true) { - - /** - * Bundle where the view state of the holders is saved. - */ - private var bundle = Bundle() - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: List?) { - super.onBindViewHolder(holder, position, payloads) - restoreHolderState(holder) - } - - override fun onViewRecycled(holder: RecyclerView.ViewHolder) { - super.onViewRecycled(holder) - saveHolderState(holder, bundle) - } - - override fun onSaveInstanceState(outState: Bundle) { - val holdersBundle = Bundle() - allBoundViewHolders.forEach { saveHolderState(it, holdersBundle) } - outState.putBundle(HOLDER_BUNDLE_KEY, holdersBundle) - super.onSaveInstanceState(outState) - } - - override fun onRestoreInstanceState(savedInstanceState: Bundle) { - super.onRestoreInstanceState(savedInstanceState) - bundle = savedInstanceState.getBundle(HOLDER_BUNDLE_KEY) - } - - /** - * Saves the view state of the given holder. - * - * @param holder The holder to save. - * @param outState The bundle where the state is saved. - */ - private fun saveHolderState(holder: RecyclerView.ViewHolder, outState: Bundle) { - val key = "holder_${holder.adapterPosition}" - val holderState = SparseArray() - holder.itemView.saveHierarchyState(holderState) - outState.putSparseParcelableArray(key, holderState) - } - - /** - * Restores the view state of the given holder. - * - * @param holder The holder to restore. - */ - private fun restoreHolderState(holder: RecyclerView.ViewHolder) { - val key = "holder_${holder.adapterPosition}" - val holderState = bundle.getSparseParcelableArray(key) - if (holderState != null) { - holder.itemView.restoreHierarchyState(holderState) - bundle.remove(key) - } - } - - private companion object { - const val HOLDER_BUNDLE_KEY = "holder_bundle" - } -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardAdapter.kt deleted file mode 100644 index 9b3b71b0ac..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardAdapter.kt +++ /dev/null @@ -1,28 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.kanade.tachiyomi.data.database.models.Manga - -/** - * Adapter that holds the manga items from search results. - * - * @param controller instance of [CatalogueSearchController]. - */ -class CatalogueSearchCardAdapter(controller: CatalogueSearchController) : - FlexibleAdapter(null, controller, true) { - - /** - * Listen for browse item clicks. - */ - val mangaClickListener: OnMangaClickListener = controller - - /** - * Listener which should be called when user clicks browse. - * Note: Should only be handled by [CatalogueSearchController] - */ - interface OnMangaClickListener { - fun onMangaClick(manga: Manga) - fun onMangaLongClick(manga: Manga) - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardHolder.kt deleted file mode 100644 index cf21e74374..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardHolder.kt +++ /dev/null @@ -1,52 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import android.view.View -import com.bumptech.glide.load.engine.DiskCacheStrategy -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.glide.GlideApp -import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder -import eu.kanade.tachiyomi.widget.StateImageViewTarget -import kotlinx.android.synthetic.main.catalogue_global_search_controller_card_item.* - -class CatalogueSearchCardHolder(view: View, adapter: CatalogueSearchCardAdapter) - : BaseFlexibleViewHolder(view, adapter) { - - init { - // Call onMangaClickListener when item is pressed. - itemView.setOnClickListener { - val item = adapter.getItem(adapterPosition) - if (item != null) { - adapter.mangaClickListener.onMangaClick(item.manga) - } - } - itemView.setOnLongClickListener { - val item = adapter.getItem(adapterPosition) - if (item != null) { - adapter.mangaClickListener.onMangaLongClick(item.manga) - } - true - } - } - - fun bind(manga: Manga) { - tvTitle.text = manga.title - // Set alpha of thumbnail. - itemImage.alpha = if (manga.favorite) 0.3f else 1.0f - - setImage(manga) - } - - fun setImage(manga: Manga) { - GlideApp.with(itemView.context).clear(itemImage) - if (!manga.thumbnail_url.isNullOrEmpty()) { - GlideApp.with(itemView.context) - .load(manga) - .diskCacheStrategy(DiskCacheStrategy.DATA) - .centerCrop() - .skipMemoryCache(true) - .placeholder(android.R.color.transparent) - .into(StateImageViewTarget(itemImage, progress)) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardItem.kt deleted file mode 100644 index 3d43b12e96..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchCardItem.kt +++ /dev/null @@ -1,35 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import android.view.View -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.Manga - -class CatalogueSearchCardItem(val manga: Manga) : AbstractFlexibleItem() { - - override fun getLayoutRes(): Int { - return R.layout.catalogue_global_search_controller_card_item - } - - override fun createViewHolder(view: View, adapter: FlexibleAdapter<*>): CatalogueSearchCardHolder { - return CatalogueSearchCardHolder(view, adapter as CatalogueSearchCardAdapter) - } - - override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: CatalogueSearchCardHolder, - position: Int, payloads: List?) { - holder.bind(manga) - } - - override fun equals(other: Any?): Boolean { - if (other is CatalogueSearchCardItem) { - return manga.id == other.manga.id - } - return false - } - - override fun hashCode(): Int { - return manga.id?.toInt() ?: 0 - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt deleted file mode 100644 index 77e23a6ba3..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt +++ /dev/null @@ -1,188 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import android.os.Bundle -import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.SearchView -import android.view.* -import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.source.CatalogueSource -import eu.kanade.tachiyomi.ui.base.controller.NucleusController -import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction -import eu.kanade.tachiyomi.ui.manga.MangaController -import kotlinx.android.synthetic.main.catalogue_global_search_controller.* - -/** - * This controller shows and manages the different search result in global search. - * This controller should only handle UI actions, IO actions should be done by [CatalogueSearchPresenter] - * [CatalogueSearchCardAdapter.OnMangaClickListener] called when manga is clicked in global search - */ -open class CatalogueSearchController(protected val initialQuery: String? = null) : - NucleusController(), - CatalogueSearchCardAdapter.OnMangaClickListener { - - /** - * Adapter containing search results grouped by lang. - */ - protected var adapter: CatalogueSearchAdapter? = null - - /** - * Called when controller is initialized. - */ - init { - setHasOptionsMenu(true) - } - - /** - * Initiate the view with [R.layout.catalogue_global_search_controller]. - * - * @param inflater used to load the layout xml. - * @param container containing parent views. - * @return inflated view - */ - override fun inflateView(inflater: LayoutInflater, container: ViewGroup): android.view.View { - return inflater.inflate(R.layout.catalogue_global_search_controller, container, false) - } - - /** - * Set the title of controller. - * - * @return title. - */ - override fun getTitle(): String? { - return presenter.query - } - - /** - * Create the [CatalogueSearchPresenter] used in controller. - * - * @return instance of [CatalogueSearchPresenter] - */ - override fun createPresenter(): CatalogueSearchPresenter { - return CatalogueSearchPresenter(initialQuery) - } - - /** - * Called when manga in global search is clicked, opens manga. - * - * @param manga clicked item containing manga information. - */ - override fun onMangaClick(manga: Manga) { - // Open MangaController. - router.pushController(MangaController(manga, true).withFadeTransaction()) - } - - /** - * Called when manga in global search is long clicked. - * - * @param manga clicked item containing manga information. - */ - override fun onMangaLongClick(manga: Manga) { - // Delegate to single click by default. - onMangaClick(manga) - } - - /** - * Adds items to the options menu. - * - * @param menu menu containing options. - * @param inflater used to load the menu xml. - */ - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - // Inflate menu. - inflater.inflate(R.menu.catalogue_new_list, menu) - - // Initialize search menu - val searchItem = menu.findItem(R.id.action_search) - val searchView = searchItem.actionView as SearchView - - searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { - override fun onMenuItemActionExpand(item: MenuItem?): Boolean { - searchView.onActionViewExpanded() // Required to show the query in the view - searchView.setQuery(presenter.query, false) - return true - } - - override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { - return true - } - }) - - searchView.queryTextChangeEvents() - .filter { it.isSubmitted } - .subscribeUntilDestroy { - presenter.search(it.queryText().toString()) - searchItem.collapseActionView() - setTitle() // Update toolbar title - } - } - - /** - * Called when the view is created - * - * @param view view of controller - */ - override fun onViewCreated(view: View) { - super.onViewCreated(view) - - adapter = CatalogueSearchAdapter(this) - - // Create recycler and set adapter. - recycler.layoutManager = LinearLayoutManager(view.context) - recycler.adapter = adapter - } - - override fun onDestroyView(view: View) { - adapter = null - super.onDestroyView(view) - } - - override fun onSaveViewState(view: View, outState: Bundle) { - super.onSaveViewState(view, outState) - adapter?.onSaveInstanceState(outState) - } - - override fun onRestoreViewState(view: View, savedViewState: Bundle) { - super.onRestoreViewState(view, savedViewState) - adapter?.onRestoreInstanceState(savedViewState) - } - - /** - * Returns the view holder for the given manga. - * - * @param source used to find holder containing source - * @return the holder of the manga or null if it's not bound. - */ - private fun getHolder(source: CatalogueSource): CatalogueSearchHolder? { - val adapter = adapter ?: return null - - adapter.allBoundViewHolders.forEach { holder -> - val item = adapter.getItem(holder.adapterPosition) - if (item != null && source.id == item.source.id) { - return holder as CatalogueSearchHolder - } - } - - return null - } - - /** - * Add search result to adapter. - * - * @param searchResult result of search. - */ - fun setItems(searchResult: List) { - adapter?.updateDataSet(searchResult) - } - - /** - * Called from the presenter when a manga is initialized. - * - * @param manga the initialized manga. - */ - fun onMangaInitialized(source: CatalogueSource, manga: Manga) { - getHolder(source)?.setImage(manga) - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchHolder.kt deleted file mode 100644 index d189ada45c..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchHolder.kt +++ /dev/null @@ -1,99 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import android.support.v7.widget.LinearLayoutManager -import android.view.View -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder -import eu.kanade.tachiyomi.util.getResourceColor -import eu.kanade.tachiyomi.util.gone -import eu.kanade.tachiyomi.util.setVectorCompat -import eu.kanade.tachiyomi.util.visible -import kotlinx.android.synthetic.main.catalogue_global_search_controller_card.* - -/** - * Holder that binds the [CatalogueSearchItem] containing catalogue cards. - * - * @param view view of [CatalogueSearchItem] - * @param adapter instance of [CatalogueSearchAdapter] - */ -class CatalogueSearchHolder(view: View, val adapter: CatalogueSearchAdapter) : - BaseFlexibleViewHolder(view, adapter) { - - /** - * Adapter containing manga from search results. - */ - private val mangaAdapter = CatalogueSearchCardAdapter(adapter.controller) - - private var lastBoundResults: List? = null - - init { - // Set layout horizontal. - recycler.layoutManager = LinearLayoutManager(view.context, LinearLayoutManager.HORIZONTAL, false) - recycler.adapter = mangaAdapter - - nothing_found_icon.setVectorCompat(R.drawable.ic_search_black_112dp, - view.context.getResourceColor(android.R.attr.textColorHint)) - } - - /** - * Show the loading of source search result. - * - * @param item item of card. - */ - fun bind(item: CatalogueSearchItem) { - val source = item.source - val results = item.results - - val titlePrefix = if (item.highlighted) "▶" else "" - val langSuffix = if (source.lang.isNotEmpty()) " (${source.lang})" else "" - - // Set Title with country code if available. - title.text = titlePrefix + source.name + langSuffix - - when { - results == null -> { - progress.visible() - nothing_found.gone() - } - results.isEmpty() -> { - progress.gone() - nothing_found.visible() - } - else -> { - progress.gone() - nothing_found.gone() - } - } - if (results !== lastBoundResults) { - mangaAdapter.updateDataSet(results) - lastBoundResults = results - } - } - - /** - * Called from the presenter when a manga is initialized. - * - * @param manga the initialized manga. - */ - fun setImage(manga: Manga) { - getHolder(manga)?.setImage(manga) - } - - /** - * Returns the view holder for the given manga. - * - * @param manga the manga to find. - * @return the holder of the manga or null if it's not bound. - */ - private fun getHolder(manga: Manga): CatalogueSearchCardHolder? { - mangaAdapter.allBoundViewHolders.forEach { holder -> - val item = mangaAdapter.getItem(holder.adapterPosition) - if (item != null && item.manga.id!! == manga.id!!) { - return holder as CatalogueSearchCardHolder - } - } - - return null - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchItem.kt deleted file mode 100644 index 9fe950082c..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchItem.kt +++ /dev/null @@ -1,66 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import android.view.View -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.source.CatalogueSource - -/** - * Item that contains search result information. - * - * @param source the source for the search results. - * @param results the search results. - * @param highlighted whether this search item should be highlighted/marked in the catalogue search view. - */ -class CatalogueSearchItem(val source: CatalogueSource, val results: List?, val highlighted: Boolean = false) - : AbstractFlexibleItem() { - - /** - * Set view. - * - * @return id of view - */ - override fun getLayoutRes(): Int { - return R.layout.catalogue_global_search_controller_card - } - - /** - * Create view holder (see [CatalogueSearchAdapter]. - * - * @return holder of view. - */ - override fun createViewHolder(view: View, adapter: FlexibleAdapter<*>): CatalogueSearchHolder { - return CatalogueSearchHolder(view, adapter as CatalogueSearchAdapter) - } - - /** - * Bind item to view. - */ - override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: CatalogueSearchHolder, - position: Int, payloads: List?) { - holder.bind(this) - } - - /** - * Used to check if two items are equal. - * - * @return items are equal? - */ - override fun equals(other: Any?): Boolean { - if (other is CatalogueSearchItem) { - return source.id == other.source.id - } - return false - } - - /** - * Return hash code of item. - * - * @return hashcode - */ - override fun hashCode(): Int { - return source.id.toInt() - } - -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchPresenter.kt deleted file mode 100644 index cba9dc3b20..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchPresenter.kt +++ /dev/null @@ -1,222 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue.global_search - -import android.os.Bundle -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.source.CatalogueSource -import eu.kanade.tachiyomi.source.Source -import eu.kanade.tachiyomi.source.SourceManager -import eu.kanade.tachiyomi.source.model.FilterList -import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.source.online.LoginSource -import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter -import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCataloguePresenter -import rx.Observable -import rx.Subscription -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers -import rx.subjects.PublishSubject -import timber.log.Timber -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get - -/** - * Presenter of [CatalogueSearchController] - * Function calls should be done from here. UI calls should be done from the controller. - * - * @param sourceManager manages the different sources. - * @param db manages the database calls. - * @param preferencesHelper manages the preference calls. - */ -open class CatalogueSearchPresenter( - val initialQuery: String? = "", - val sourceManager: SourceManager = Injekt.get(), - val db: DatabaseHelper = Injekt.get(), - val preferencesHelper: PreferencesHelper = Injekt.get() -) : BasePresenter() { - - /** - * Enabled sources. - */ - val sources by lazy { getEnabledSources() } - - /** - * Query from the view. - */ - var query = "" - private set - - /** - * Fetches the different sources by user settings. - */ - private var fetchSourcesSubscription: Subscription? = null - - /** - * Subject which fetches image of given manga. - */ - private val fetchImageSubject = PublishSubject.create, Source>>() - - /** - * Subscription for fetching images of manga. - */ - private var fetchImageSubscription: Subscription? = null - - override fun onCreate(savedState: Bundle?) { - super.onCreate(savedState) - - // Perform a search with previous or initial state - search(savedState?.getString(BrowseCataloguePresenter::query.name) ?: initialQuery.orEmpty()) - } - - override fun onDestroy() { - fetchSourcesSubscription?.unsubscribe() - fetchImageSubscription?.unsubscribe() - super.onDestroy() - } - - override fun onSave(state: Bundle) { - state.putString(BrowseCataloguePresenter::query.name, query) - super.onSave(state) - } - - /** - * Returns a list of enabled sources ordered by language and name. - * - * @return list containing enabled sources. - */ - protected open fun getEnabledSources(): List { - val languages = preferencesHelper.enabledLanguages().getOrDefault() - val hiddenCatalogues = preferencesHelper.hiddenCatalogues().getOrDefault() - - return sourceManager.getCatalogueSources() - .filter { it.lang in languages } - .filterNot { it is LoginSource && !it.isLogged() } - .filterNot { it.id.toString() in hiddenCatalogues } - .sortedBy { "(${it.lang}) ${it.name}" } - } - - /** - * Creates a catalogue search item - */ - protected open fun createCatalogueSearchItem(source: CatalogueSource, results: List?): CatalogueSearchItem { - return CatalogueSearchItem(source, results) - } - - /** - * Initiates a search for manga per catalogue. - * - * @param query query on which to search. - */ - fun search(query: String) { - // Return if there's nothing to do - if (this.query == query) return - - // Update query - this.query = query - - // Create image fetch subscription - initializeFetchImageSubscription() - - // Create items with the initial state - val initialItems = sources.map { createCatalogueSearchItem(it, null) } - var items = initialItems - - fetchSourcesSubscription?.unsubscribe() - fetchSourcesSubscription = Observable.from(sources) - .flatMap({ source -> - source.fetchSearchManga(1, query, FilterList()) - .subscribeOn(Schedulers.io()) - .onExceptionResumeNext(Observable.empty()) // Ignore timeouts. - .map { it.mangas.take(10) } // Get at most 10 manga from search result. - .map { it.map { networkToLocalManga(it, source.id) } } // Convert to local manga. - .doOnNext { fetchImage(it, source) } // Load manga covers. - .map { createCatalogueSearchItem(source, it.map { CatalogueSearchCardItem(it) }) } - }, 5) - .observeOn(AndroidSchedulers.mainThread()) - // Update matching source with the obtained results - .map { result -> - items.map { item -> if (item.source == result.source) result else item } - } - // Update current state - .doOnNext { items = it } - // Deliver initial state - .startWith(initialItems) - .subscribeLatestCache({ view, manga -> - view.setItems(manga) - }, { _, error -> - Timber.e(error) - }) - } - - /** - * Initialize a list of manga. - * - * @param manga the list of manga to initialize. - */ - private fun fetchImage(manga: List, source: Source) { - fetchImageSubject.onNext(Pair(manga, source)) - } - - /** - * Subscribes to the initializer of manga details and updates the view if needed. - */ - private fun initializeFetchImageSubscription() { - fetchImageSubscription?.unsubscribe() - fetchImageSubscription = fetchImageSubject.observeOn(Schedulers.io()) - .flatMap { - val source = it.second - Observable.from(it.first).filter { it.thumbnail_url == null && !it.initialized } - .map { Pair(it, source) } - .concatMap { getMangaDetailsObservable(it.first, it.second) } - .map { Pair(source as CatalogueSource, it) } - - } - - .onBackpressureBuffer() - .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ (source, manga) -> - @Suppress("DEPRECATION") - view?.onMangaInitialized(source, manga) - }, { error -> - Timber.e(error) - }) - } - - /** - * Returns an observable of manga that initializes the given manga. - * - * @param manga the manga to initialize. - * @return an observable of the manga to initialize - */ - private fun getMangaDetailsObservable(manga: Manga, source: Source): Observable { - return source.fetchMangaDetails(manga) - .flatMap { networkManga -> - manga.copyFrom(networkManga) - manga.initialized = true - db.insertManga(manga).executeAsBlocking() - Observable.just(manga) - } - .onErrorResumeNext { Observable.just(manga) } - } - - /** - * Returns a manga from the database for the given manga from network. It creates a new entry - * if the manga is not yet in the database. - * - * @param sManga the manga from the source. - * @return a manga from the database. - */ - private fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking() - if (localManga == null) { - val newManga = Manga.create(sManga.url, sManga.title, sourceId) - newManga.copyFrom(sManga) - val result = db.insertManga(newManga).executeAsBlocking() - newManga.id = result.insertedId() - localManga = newManga - } - return localManga - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 8271ff074c..fdbba26448 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -193,8 +193,8 @@ class LibraryPresenter( manga1TotalChapter.compareTo(mange2TotalChapter) } LibrarySort.SOURCE -> { - val source1Name = sourceManager.getOrStub(i1.manga.source).name - val source2Name = sourceManager.getOrStub(i2.manga.source).name + val source1Name = sourceManager.getSource(i1.manga.source).name + val source2Name = sourceManager.getSource(i2.manga.source).name source1Name.compareTo(source2Name) } else -> throw Exception("Unknown sorting mode") diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index fbce67a020..f94a1cbfc5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -13,26 +13,36 @@ import com.bluelinelabs.conductor.* import eu.kanade.tachiyomi.Migrations import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.source.CatalogueSource +import eu.kanade.tachiyomi.source.Source +import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.source.online.LoginSource +import eu.kanade.tachiyomi.source.online.english.Mangadex import eu.kanade.tachiyomi.ui.base.activity.BaseActivity import eu.kanade.tachiyomi.ui.base.controller.* -import eu.kanade.tachiyomi.ui.catalogue.CatalogueController -import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController +import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController import eu.kanade.tachiyomi.ui.download.DownloadController import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController import eu.kanade.tachiyomi.ui.setting.SettingsMainController +import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog import kotlinx.android.synthetic.main.main_activity.* +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy -class MainActivity : BaseActivity() { +class MainActivity : BaseActivity(), SourceLoginDialog.Listener { private lateinit var router: Router val preferences: PreferencesHelper by injectLazy() + val source : LoginSource by lazy { Injekt.get().getSources()[0] as LoginSource } + private var drawerArrow: DrawerArrowDrawable? = null private var secondaryDrawer: ViewGroup? = null @@ -81,7 +91,15 @@ class MainActivity : BaseActivity() { R.id.nav_drawer_library -> setRoot(LibraryController(), id) R.id.nav_drawer_recent_updates -> setRoot(RecentChaptersController(), id) R.id.nav_drawer_recently_read -> setRoot(RecentlyReadController(), id) - R.id.nav_drawer_catalogues -> setRoot(CatalogueController(), id) + R.id.nav_drawer_browse -> { + val browseCatalogueController = BrowseCatalogueController(source as CatalogueSource) + setRoot(browseCatalogueController, id) + if (!source.isLogged()) { + val dialog = SourceLoginDialog(source) + dialog.targetController = browseCatalogueController + dialog.showDialog(router) + } + } R.id.nav_drawer_downloads -> { router.pushController(DownloadController().withFadeTransaction()) } @@ -136,6 +154,19 @@ class MainActivity : BaseActivity() { } } + /** + * Called when login dialog is closed, refreshes the adapter. + * + * @param source clicked item containing source information. + */ + override fun loginDialogClosed(source: LoginSource) { + if (source.isLogged()) { + router.popCurrentController() + R.id.nav_drawer_browse + setRoot(BrowseCatalogueController(source as CatalogueSource),R.id.nav_drawer_browse) + } + } + override fun onNewIntent(intent: Intent) { if (!handleIntentAction(intent)) { super.onNewIntent(intent) @@ -147,7 +178,7 @@ class MainActivity : BaseActivity() { SHORTCUT_LIBRARY -> setSelectedDrawerItem(R.id.nav_drawer_library) SHORTCUT_RECENTLY_UPDATED -> setSelectedDrawerItem(R.id.nav_drawer_recent_updates) SHORTCUT_RECENTLY_READ -> setSelectedDrawerItem(R.id.nav_drawer_recently_read) - SHORTCUT_CATALOGUES -> setSelectedDrawerItem(R.id.nav_drawer_catalogues) + SHORTCUT_CATALOGUES -> setSelectedDrawerItem(R.id.nav_drawer_browse) SHORTCUT_MANGA -> { val extras = intent.extras ?: return false router.setRoot(RouterTransaction.with(MangaController(extras))) @@ -161,10 +192,10 @@ class MainActivity : BaseActivity() { //If the intent match the "standard" Android search intent // or the Google-specific search intent (triggered by saying or typing "search *query* on *Tachiyomi*" in Google Search/Google Assistant) - setSelectedDrawerItem(R.id.nav_drawer_catalogues) + setSelectedDrawerItem(R.id.nav_drawer_browse) //Get the search query provided in extras, and if not null, perform a global search with it. intent.getStringExtra(SearchManager.QUERY)?.also { query -> - router.pushController(CatalogueSearchController(query).withFadeTransaction()) + router.pushController(BrowseCatalogueController(source as CatalogueSource).withFadeTransaction()) } } else -> return false @@ -248,7 +279,7 @@ class MainActivity : BaseActivity() { const val SHORTCUT_LIBRARY = "eu.kanade.tachiyomi.SHOW_LIBRARY" const val SHORTCUT_RECENTLY_UPDATED = "eu.kanade.tachiyomi.SHOW_RECENTLY_UPDATED" const val SHORTCUT_RECENTLY_READ = "eu.kanade.tachiyomi.SHOW_RECENTLY_READ" - const val SHORTCUT_CATALOGUES = "eu.kanade.tachiyomi.SHOW_CATALOGUES" + const val SHORTCUT_CATALOGUES = "eu.kanade.tachiyomi.SHOW_BROWSE" const val SHORTCUT_DOWNLOADS = "eu.kanade.tachiyomi.SHOW_DOWNLOADS" const val SHORTCUT_MANGA = "eu.kanade.tachiyomi.SHOW_MANGA" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index c56cc7541c..1591f496bb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -44,7 +44,7 @@ class MangaController : RxController, TabbedController { }) { this.manga = manga if (manga != null) { - source = Injekt.get().getOrStub(manga.source) + source = Injekt.get().getSource(manga.source) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt index 138862b29b..6587f4e889 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt @@ -37,7 +37,6 @@ import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction -import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController import eu.kanade.tachiyomi.ui.library.ChangeMangaCategoriesDialog import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaController @@ -51,7 +50,7 @@ import kotlinx.android.synthetic.main.manga_info_controller.* import uy.kohesive.injekt.injectLazy import java.text.DateFormat import java.text.DecimalFormat -import java.util.Date +import java.util.* /** * Fragment that shows manga information. @@ -94,25 +93,25 @@ class MangaInfoController : NucleusController(), copyToClipboard(view.context.getString(R.string.title), manga_full_title.text.toString()) } - manga_full_title.clicks().subscribeUntilDestroy { - performGlobalSearch(manga_full_title.text.toString()) - } + /*manga_full_title.clicks().subscribeUntilDestroy { + performGlobalSearch(manga_full_title.text.toString()) + }*/ manga_artist.longClicks().subscribeUntilDestroy { copyToClipboard(manga_artist_label.text.toString(), manga_artist.text.toString()) } - manga_artist.clicks().subscribeUntilDestroy { + /* manga_artist.clicks().subscribeUntilDestroy { performGlobalSearch(manga_artist.text.toString()) - } + }*/ manga_author.longClicks().subscribeUntilDestroy { copyToClipboard(manga_author.text.toString(), manga_author.text.toString()) } - manga_author.clicks().subscribeUntilDestroy { + /* manga_author.clicks().subscribeUntilDestroy { performGlobalSearch(manga_author.text.toString()) - } + }*/ manga_summary.longClicks().subscribeUntilDestroy { copyToClipboard(view.context.getString(R.string.description), manga_summary.text.toString()) @@ -504,16 +503,6 @@ class MangaInfoController : NucleusController(), Toast.LENGTH_SHORT) } - /** - * Perform a global search using the provided query. - * - * @param query the search query to pass to the search controller - */ - fun performGlobalSearch(query: String) { - val router = parentController?.router ?: return - router.pushController(CatalogueSearchController(query).withFadeTransaction()) - } - /** * Create shortcut using ShortcutManager. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index b9a37b8fd2..8ee0c4a0b0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -194,7 +194,7 @@ class ReaderPresenter( this.manga = manga if (chapterId == -1L) chapterId = initialChapterId - val source = sourceManager.getOrStub(manga.source) + val source = sourceManager.getSource(manga.source) loader = ChapterLoader(downloadManager, manga, source) Observable.just(manga).subscribeLatestCache(ReaderActivity::setManga) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadHolder.kt index 64eab1a9b1..461f1e62f5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadHolder.kt @@ -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.getOrStub(manga.source).toString(), formattedNumber) + .format(adapter.sourceManager.getSource(manga.source).toString(), formattedNumber) // Set last read timestamp title last_read.text = adapter.dateFormat.format(Date(history.last_read)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 56cfa769db..a0cf351659 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -17,6 +17,12 @@ class SettingsMainController : SettingsController() { titleRes = R.string.pref_category_general onClick { navigateTo(SettingsGeneralController()) } } + preference { + iconRes = R.drawable.ic_language_black_24dp + iconTint = tintColor + titleRes = R.string.pref_category_site_specific + onClick { navigateTo(SettingsSiteController()) } + } preference { iconRes = R.drawable.ic_chrome_reader_mode_black_24dp iconTint = tintColor diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSiteController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSiteController.kt new file mode 100644 index 0000000000..c06b2814f1 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSiteController.kt @@ -0,0 +1,54 @@ +package eu.kanade.tachiyomi.ui.setting + +import android.support.v7.preference.PreferenceScreen +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.preference.PreferenceKeys +import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.source.online.LoginSource +import eu.kanade.tachiyomi.widget.preference.LoginCheckBoxPreference +import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get + +class SettingsSiteController : SettingsController(), SourceLoginDialog.Listener { + + private val sources by lazy { Injekt.get().getSources() as List } + + override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + titleRes = R.string.pref_site_specific_settings + + listPreference { + key = PreferenceKeys.showR18 + titleRes = R.string.pref_show_r18_title + entriesRes = arrayOf(R.string.pref_show_r18_no, R.string.pref_show_r18_all, R.string.pref_show_r18_show) + entryValues = arrayOf("0", "1", "2") + summary = "%s" + + } + + val sourcePreference = LoginCheckBoxPreference(context, sources[0] ).apply { + val id = source.id.toString() + title = source.name + key = getSourceKey(source.id) + isPersistent = false + + setOnLoginClickListener { + val dialog = SourceLoginDialog(source) + dialog.targetController = this@SettingsSiteController + dialog.showDialog(router) + } + } + + preferenceScreen.addPreference(sourcePreference) + + + } + override fun loginDialogClosed(source: LoginSource) { + val pref = findPreference(getSourceKey(source.id)) as? LoginCheckBoxPreference + pref?.notifyChanged() + } + private fun getSourceKey(sourceId: Long): String { + return "source_$sourceId" + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSourcesController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSourcesController.kt deleted file mode 100644 index 6becc8d35e..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSourcesController.kt +++ /dev/null @@ -1,118 +0,0 @@ -package eu.kanade.tachiyomi.ui.setting - -import android.graphics.drawable.Drawable -import android.support.v7.preference.PreferenceGroup -import android.support.v7.preference.PreferenceScreen -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.source.SourceManager -import eu.kanade.tachiyomi.source.online.HttpSource -import eu.kanade.tachiyomi.source.online.LoginSource -import eu.kanade.tachiyomi.util.LocaleHelper -import eu.kanade.tachiyomi.widget.preference.LoginCheckBoxPreference -import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog -import eu.kanade.tachiyomi.widget.preference.SwitchPreferenceCategory -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import java.util.* - -class SettingsSourcesController : SettingsController(), - SourceLoginDialog.Listener { - - private val onlineSources by lazy { Injekt.get().getOnlineSources() } - - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { - titleRes = R.string.pref_category_sources - - // Get the list of active language codes. - val activeLangsCodes = preferences.enabledLanguages().getOrDefault() - - // Get a map of sources grouped by language. - val sourcesByLang = onlineSources.groupByTo(TreeMap(), { it.lang }) - - // Order first by active languages, then inactive ones - val orderedLangs = sourcesByLang.keys.filter { it in activeLangsCodes } + - sourcesByLang.keys.filterNot { it in activeLangsCodes } - - orderedLangs.forEach { lang -> - val sources = sourcesByLang[lang].orEmpty().sortedBy { it.name } - - // Create a preference group and set initial state and change listener - SwitchPreferenceCategory(context).apply { - preferenceScreen.addPreference(this) - title = LocaleHelper.getDisplayName(lang, context) - isPersistent = false - if (lang in activeLangsCodes) { - setChecked(true) - addLanguageSources(this, sources) - } - - onChange { newValue -> - val checked = newValue as Boolean - val current = preferences.enabledLanguages().getOrDefault() - if (!checked) { - preferences.enabledLanguages().set(current - lang) - removeAll() - } else { - preferences.enabledLanguages().set(current + lang) - addLanguageSources(this, sources) - } - true - } - } - } - } - - override fun setDivider(divider: Drawable?) { - super.setDivider(null) - } - - /** - * Adds the source list for the given group (language). - * - * @param group the language category. - */ - private fun addLanguageSources(group: PreferenceGroup, sources: List) { - val hiddenCatalogues = preferences.hiddenCatalogues().getOrDefault() - - sources.forEach { source -> - val sourcePreference = LoginCheckBoxPreference(group.context, source).apply { - val id = source.id.toString() - title = source.name - key = getSourceKey(source.id) - isPersistent = false - isChecked = id !in hiddenCatalogues - - onChange { newValue -> - val checked = newValue as Boolean - val current = preferences.hiddenCatalogues().getOrDefault() - - preferences.hiddenCatalogues().set(if (checked) - current - id - else - current + id) - - true - } - - setOnLoginClickListener { - val dialog = SourceLoginDialog(source) - dialog.targetController = this@SettingsSourcesController - dialog.showDialog(router) - } - } - - group.addPreference(sourcePreference) - } - } - - override fun loginDialogClosed(source: LoginSource) { - val pref = findPreference(getSourceKey(source.id)) as? LoginCheckBoxPreference - pref?.notifyChanged() - } - - private fun getSourceKey(sourceId: Long): String { - return "source_$sourceId" - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt index b27c77c62b..f077e2f988 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt @@ -10,10 +10,17 @@ import com.bluelinelabs.conductor.ControllerChangeType import com.dd.processbutton.iml.ActionProcessButton import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.source.online.LoginSource import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction +import eu.kanade.tachiyomi.ui.manga.info.MangaWebViewController import eu.kanade.tachiyomi.widget.SimpleTextWatcher import kotlinx.android.synthetic.main.pref_account_login.view.* import rx.Subscription +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy abstract class LoginDialogPreference(bundle: Bundle? = null) : DialogController(bundle) { @@ -37,6 +44,8 @@ abstract class LoginDialogPreference(bundle: Bundle? = null) : DialogController( } fun onViewCreated(view: View) { + val source = Injekt.get().get(args.getLong("key")) as LoginSource? + v = view.apply { show_password.setOnCheckedChangeListener { _, isChecked -> if (isChecked) @@ -47,6 +56,15 @@ abstract class LoginDialogPreference(bundle: Bundle? = null) : DialogController( login.setMode(ActionProcessButton.Mode.ENDLESS) login.setOnClickListener { checkLogin() } + if(source != null && source is HttpSource){ + login_captcha.setOnClickListener { + router.pushController(MangaWebViewController(source.id, source.baseUrl) + .withFadeTransaction()) + } + } else{ + login_captcha.visibility =View.GONE + } + setCredentialsOnView(this) diff --git a/app/src/main/res/drawable/ic_new_box_black_24dp.xml b/app/src/main/res/drawable/ic_new_box_black_24dp.xml new file mode 100644 index 0000000000..6610193d07 --- /dev/null +++ b/app/src/main/res/drawable/ic_new_box_black_24dp.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/pref_account_login.xml b/app/src/main/res/layout/pref_account_login.xml index c0a96a6596..866db2c063 100644 --- a/app/src/main/res/layout/pref_account_login.xml +++ b/app/src/main/res/layout/pref_account_login.xml @@ -63,4 +63,13 @@ app:pb_textError="@string/invalid_login" app:pb_textProgress="@string/loading"/> +