mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Support for sources from different languages
This commit is contained in:
		| @@ -379,11 +379,11 @@ public class DownloadManager { | ||||
|     } | ||||
|  | ||||
|     public File getAbsoluteMangaDirectory(Source source, Manga manga) { | ||||
|         String chapterRelativePath = source.getName() + | ||||
|         String mangaRelativePath = source.getVisibleName() + | ||||
|                 File.separator + | ||||
|                 manga.title.replaceAll("[^\\sa-zA-Z0-9.-]", "_"); | ||||
|  | ||||
|         return new File(preferences.getDownloadsDirectory(), chapterRelativePath); | ||||
|         return new File(preferences.getDownloadsDirectory(), mangaRelativePath); | ||||
|     } | ||||
|  | ||||
|     // Get the absolute path to the chapter directory | ||||
|   | ||||
| @@ -11,9 +11,7 @@ import eu.kanade.tachiyomi.data.source.base.Source | ||||
| import java.io.File | ||||
| import java.io.IOException | ||||
|  | ||||
| fun <T> Preference<T>.getOrDefault(): T { | ||||
|     return get() ?: defaultValue()!! | ||||
| } | ||||
| fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!! | ||||
|  | ||||
| class PreferencesHelper(private val context: Context) { | ||||
|  | ||||
| @@ -140,6 +138,10 @@ class PreferencesHelper(private val context: Context) { | ||||
|         return rxPrefs.getBoolean(getKey(R.string.pref_display_catalogue_as_list), false) | ||||
|     } | ||||
|  | ||||
|     fun enabledLanguages(): Preference<MutableSet<String>> { | ||||
|         return rxPrefs.getStringSet(getKey(R.string.pref_source_languages), setOf("EN")) | ||||
|     } | ||||
|  | ||||
|     fun getSourceUsername(source: Source): String { | ||||
|         return prefs.getString(SOURCE_ACCOUNT_USERNAME + source.id, "") | ||||
|     } | ||||
|   | ||||
| @@ -0,0 +1,8 @@ | ||||
| package eu.kanade.tachiyomi.data.source | ||||
|  | ||||
| class Language(val lang: String, val code: String) | ||||
|  | ||||
| val EN = Language("English", "EN") | ||||
| val RU = Language("Russian", "RU") | ||||
|  | ||||
| fun getLanguages(): List<Language> = listOf(EN, RU) | ||||
| @@ -11,7 +11,6 @@ import java.util.* | ||||
| open class SourceManager(private val context: Context) { | ||||
|  | ||||
|     val sourcesMap: HashMap<Int, Source> | ||||
|     val sources: List<Source> | ||||
|  | ||||
|     val BATOTO = 1 | ||||
|     val MANGAHERE = 2 | ||||
| @@ -22,7 +21,6 @@ open class SourceManager(private val context: Context) { | ||||
|  | ||||
|     init { | ||||
|         sourcesMap = createSourcesMap() | ||||
|         sources = ArrayList(sourcesMap.values).sortedBy { it.name } | ||||
|     } | ||||
|  | ||||
|     open fun get(sourceKey: Int): Source? { | ||||
| @@ -49,4 +47,6 @@ open class SourceManager(private val context: Context) { | ||||
|         return map | ||||
|     } | ||||
|  | ||||
|     fun getSources(): List<Source> = ArrayList(sourcesMap.values) | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import java.util.List; | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter; | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga; | ||||
| import eu.kanade.tachiyomi.data.source.Language; | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage; | ||||
| import okhttp3.Headers; | ||||
| import okhttp3.Response; | ||||
| @@ -24,9 +25,16 @@ public abstract class BaseSource { | ||||
|         this.id = id; | ||||
|     } | ||||
|  | ||||
|     public abstract Language getLang(); | ||||
|  | ||||
|     // Name of the source to display | ||||
|     public abstract String getName(); | ||||
|  | ||||
|     // Name of the source to display with the language | ||||
|     public String getVisibleName() { | ||||
|         return getName() + " (" + getLang().getCode() + ")"; | ||||
|     } | ||||
|  | ||||
|     // Base url of the source, like: http://example.com | ||||
|     public abstract String getBaseUrl(); | ||||
|  | ||||
| @@ -86,6 +94,6 @@ public abstract class BaseSource { | ||||
|  | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return getName(); | ||||
|         return getVisibleName(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,6 +28,8 @@ import java.util.regex.Pattern; | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter; | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga; | ||||
| import eu.kanade.tachiyomi.data.network.ReqKt; | ||||
| import eu.kanade.tachiyomi.data.source.Language; | ||||
| import eu.kanade.tachiyomi.data.source.LanguageKt; | ||||
| import eu.kanade.tachiyomi.data.source.base.LoginSource; | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage; | ||||
| import eu.kanade.tachiyomi.data.source.model.Page; | ||||
| @@ -40,7 +42,7 @@ import rx.Observable; | ||||
|  | ||||
| public class Batoto extends LoginSource { | ||||
|  | ||||
|     public static final String NAME = "Batoto (EN)"; | ||||
|     public static final String NAME = "Batoto"; | ||||
|     public static final String BASE_URL = "http://bato.to"; | ||||
|     public static final String POPULAR_MANGAS_URL = BASE_URL + "/search_ajax?order_cond=views&order=desc&p=%s"; | ||||
|     public static final String SEARCH_URL = BASE_URL + "/search_ajax?name=%s&p=%s"; | ||||
| @@ -79,6 +81,10 @@ public class Batoto extends LoginSource { | ||||
|         return BASE_URL; | ||||
|     } | ||||
|  | ||||
|     public Language getLang() { | ||||
|         return LanguageKt.getEN(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected Headers.Builder headersBuilder() { | ||||
|         Headers.Builder builder = super.headersBuilder(); | ||||
|   | ||||
| @@ -18,6 +18,8 @@ import java.util.regex.Pattern; | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter; | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga; | ||||
| import eu.kanade.tachiyomi.data.network.ReqKt; | ||||
| import eu.kanade.tachiyomi.data.source.Language; | ||||
| import eu.kanade.tachiyomi.data.source.LanguageKt; | ||||
| import eu.kanade.tachiyomi.data.source.base.Source; | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage; | ||||
| import eu.kanade.tachiyomi.data.source.model.Page; | ||||
| @@ -28,7 +30,7 @@ import okhttp3.Request; | ||||
|  | ||||
| public class Kissmanga extends Source { | ||||
|  | ||||
|     public static final String NAME = "Kissmanga (EN)"; | ||||
|     public static final String NAME = "Kissmanga"; | ||||
|     public static final String HOST = "kissmanga.com"; | ||||
|     public static final String IP = "93.174.95.110"; | ||||
|     public static final String BASE_URL = "http://" + IP; | ||||
| @@ -56,6 +58,10 @@ public class Kissmanga extends Source { | ||||
|         return BASE_URL; | ||||
|     } | ||||
|  | ||||
|     public Language getLang() { | ||||
|         return LanguageKt.getEN(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected String getInitialPopularMangasUrl() { | ||||
|         return String.format(POPULAR_MANGAS_URL, 1); | ||||
|   | ||||
| @@ -18,13 +18,15 @@ import java.util.Locale; | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter; | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga; | ||||
| import eu.kanade.tachiyomi.data.source.Language; | ||||
| import eu.kanade.tachiyomi.data.source.LanguageKt; | ||||
| import eu.kanade.tachiyomi.data.source.base.Source; | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage; | ||||
| import eu.kanade.tachiyomi.util.Parser; | ||||
|  | ||||
| public class Mangafox extends Source { | ||||
|  | ||||
|     public static final String NAME = "Mangafox (EN)"; | ||||
|     public static final String NAME = "Mangafox"; | ||||
|     public static final String BASE_URL = "http://mangafox.me"; | ||||
|     public static final String POPULAR_MANGAS_URL = BASE_URL + "/directory/%s"; | ||||
|     public static final String SEARCH_URL = | ||||
| @@ -44,6 +46,10 @@ public class Mangafox extends Source { | ||||
|         return BASE_URL; | ||||
|     } | ||||
|  | ||||
|     public Language getLang() { | ||||
|         return LanguageKt.getEN(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected String getInitialPopularMangasUrl() { | ||||
|         return String.format(POPULAR_MANGAS_URL, ""); | ||||
|   | ||||
| @@ -18,13 +18,15 @@ import java.util.Locale; | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter; | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga; | ||||
| import eu.kanade.tachiyomi.data.source.Language; | ||||
| import eu.kanade.tachiyomi.data.source.LanguageKt; | ||||
| import eu.kanade.tachiyomi.data.source.base.Source; | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage; | ||||
| import eu.kanade.tachiyomi.util.Parser; | ||||
|  | ||||
| public class Mangahere extends Source { | ||||
|  | ||||
|     public static final String NAME = "Mangahere (EN)"; | ||||
|     public static final String NAME = "Mangahere"; | ||||
|     public static final String BASE_URL = "http://www.mangahere.co"; | ||||
|     public static final String POPULAR_MANGAS_URL = BASE_URL + "/directory/%s"; | ||||
|     public static final String SEARCH_URL = BASE_URL + "/search.php?name=%s&page=%s&sort=views&order=za"; | ||||
| @@ -43,6 +45,10 @@ public class Mangahere extends Source { | ||||
|         return BASE_URL; | ||||
|     } | ||||
|  | ||||
|     public Language getLang() { | ||||
|         return LanguageKt.getEN(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected String getInitialPopularMangasUrl() { | ||||
|         return String.format(POPULAR_MANGAS_URL, ""); | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import eu.kanade.tachiyomi.ui.manga.info.MangaInfoPresenter; | ||||
| import eu.kanade.tachiyomi.ui.manga.myanimelist.MyAnimeListPresenter; | ||||
| import eu.kanade.tachiyomi.ui.reader.ReaderPresenter; | ||||
| import eu.kanade.tachiyomi.ui.recent.RecentChaptersPresenter; | ||||
| import eu.kanade.tachiyomi.ui.setting.SettingsAccountsFragment; | ||||
| import eu.kanade.tachiyomi.ui.setting.SettingsActivity; | ||||
|  | ||||
| @Singleton | ||||
| @@ -48,8 +47,6 @@ public interface AppComponent { | ||||
|     void inject(RecentChaptersPresenter recentChaptersPresenter); | ||||
|  | ||||
|     void inject(MangaActivity mangaActivity); | ||||
|     void inject(SettingsAccountsFragment settingsAccountsFragment); | ||||
|  | ||||
|     void inject(SettingsActivity settingsActivity); | ||||
|  | ||||
|     void inject(Source source); | ||||
|   | ||||
| @@ -1,10 +1,15 @@ | ||||
| package eu.kanade.tachiyomi.ui.base.activity | ||||
|  | ||||
| import android.graphics.Color | ||||
| import android.os.Bundle | ||||
| import android.support.design.widget.Snackbar | ||||
| import android.support.v7.app.AppCompatActivity | ||||
| import android.support.v7.widget.Toolbar | ||||
| import android.view.MenuItem | ||||
| import android.view.View | ||||
| import android.widget.TextView | ||||
| import eu.kanade.tachiyomi.App | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.injection.component.AppComponent | ||||
| import icepick.Icepick | ||||
| import org.greenrobot.eventbus.EventBus | ||||
| @@ -60,6 +65,24 @@ open class BaseActivity : AppCompatActivity() { | ||||
|         EventBus.getDefault().unregister(this) | ||||
|     } | ||||
|  | ||||
|     fun snack(text: String?, duration: Int = Snackbar.LENGTH_LONG) { | ||||
|         val snack = Snackbar.make(findViewById(android.R.id.content), text ?: getString(R.string.unknown_error), duration) | ||||
|         val textView = snack.view.findViewById(android.support.design.R.id.snackbar_text) as TextView | ||||
|         textView.setTextColor(Color.WHITE) | ||||
|         snack.show() | ||||
|     } | ||||
|  | ||||
|     fun snack(text: String?, actionRes: Int, actionFunc: () -> Unit, | ||||
|               duration: Int = Snackbar.LENGTH_LONG, view: View = findViewById(android.R.id.content)) { | ||||
|  | ||||
|         val snack = Snackbar.make(view, text ?: getString(R.string.unknown_error), duration) | ||||
|                 .setAction(actionRes, { actionFunc() }) | ||||
|  | ||||
|         val textView = snack.view.findViewById(android.support.design.R.id.snackbar_text) as TextView | ||||
|         textView.setTextColor(Color.WHITE) | ||||
|         snack.show() | ||||
|     } | ||||
|  | ||||
|     protected val applicationComponent: AppComponent | ||||
|         get() = App.get(this).component | ||||
|  | ||||
|   | ||||
| @@ -168,7 +168,7 @@ class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleViewHold | ||||
|         val themedContext = baseActivity.supportActionBar?.themedContext ?: activity | ||||
|  | ||||
|         val spinnerAdapter = ArrayAdapter(themedContext, | ||||
|                 android.R.layout.simple_spinner_item, presenter.getEnabledSources()) | ||||
|                 android.R.layout.simple_spinner_item, presenter.sources) | ||||
|         spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) | ||||
|  | ||||
|         val onItemSelected = object : AdapterView.OnItemSelectedListener { | ||||
| @@ -353,8 +353,12 @@ class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleViewHold | ||||
|      */ | ||||
|     fun onAddPageError(error: Throwable) { | ||||
|         hideProgressBar() | ||||
|         ToastUtil.showShort(context, error.message) | ||||
|         Timber.e(error, error.message) | ||||
|  | ||||
|         baseActivity.snack(error.message, R.string.action_retry, { | ||||
|             showProgressBar() | ||||
|             presenter.retryRequest() | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.data.cache.CoverCache | ||||
| 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.data.source.SourceManager | ||||
| import eu.kanade.tachiyomi.data.source.base.Source | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage | ||||
| @@ -45,7 +46,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|     /** | ||||
|      * Enabled sources. | ||||
|      */ | ||||
|     private val sources by lazy { sourceManager.sources } | ||||
|     val sources by lazy { getEnabledSources() } | ||||
|  | ||||
|     /** | ||||
|      * Active source. | ||||
| @@ -188,6 +189,13 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Retry a failed request. | ||||
|      */ | ||||
|     fun retryRequest() { | ||||
|         start(GET_MANGA_PAGE) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the observable of the network request for a page. | ||||
|      * | ||||
| @@ -308,12 +316,19 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of enabled sources. | ||||
|      * | ||||
|      * TODO filter by enabled sources. | ||||
|      * Returns a list of enabled sources ordered by language and name. | ||||
|      */ | ||||
|     fun getEnabledSources(): List<Source> { | ||||
|         return sourceManager.sources | ||||
|     private fun getEnabledSources(): List<Source> { | ||||
|         val languages = prefs.enabledLanguages().getOrDefault() | ||||
|  | ||||
|         // Ensure at least one language | ||||
|         if (languages.isEmpty()) { | ||||
|             languages.add("EN") | ||||
|         } | ||||
|  | ||||
|         return sourceManager.getSources() | ||||
|                 .filter { it.lang.code in languages } | ||||
|                 .sortedBy { "(${it.lang.code}) ${it.name}" } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -143,7 +143,7 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> { | ||||
|  | ||||
|         // If manga source is known update source TextView. | ||||
|         if (mangaSource != null) { | ||||
|             source.setText(mangaSource.getName()); | ||||
|             source.setText(mangaSource.getVisibleName()); | ||||
|         } | ||||
|  | ||||
|         // Update genres TextView. | ||||
|   | ||||
| @@ -1,76 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.setting | ||||
|  | ||||
| import android.content.Context | ||||
| import android.os.Bundle | ||||
| import android.support.v7.preference.DialogPreference | ||||
| import android.support.v7.preference.Preference | ||||
| import android.support.v7.preference.PreferenceCategory | ||||
| import android.view.View | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.source.base.Source | ||||
| import eu.kanade.tachiyomi.widget.preference.MangaSyncLoginDialog | ||||
| import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog | ||||
|  | ||||
| class SettingsAccountsFragment : SettingsNestedFragment() { | ||||
|  | ||||
|     companion object { | ||||
|  | ||||
|         fun newInstance(resourcePreference: Int, resourceTitle: Int): SettingsNestedFragment { | ||||
|             val fragment = SettingsAccountsFragment() | ||||
|             fragment.setArgs(resourcePreference, resourceTitle) | ||||
|             return fragment | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     val sourceCategory by lazy { findPreference("pref_category_source_accounts") as PreferenceCategory } | ||||
|     val syncCategory by lazy { findPreference("pref_category_manga_sync_accounts") as PreferenceCategory } | ||||
|  | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         val themedContext = preferenceManager.context | ||||
|  | ||||
|         for (source in getSourcesWithLogin()) { | ||||
|             val pref = SourcePreference(themedContext).apply { | ||||
|                 isPersistent = false | ||||
|                 title = source.name | ||||
|                 key = source.id.toString() | ||||
|                 dialogLayoutResource = R.layout.pref_account_login | ||||
|             } | ||||
|  | ||||
|             sourceCategory.addPreference(pref) | ||||
|         } | ||||
|  | ||||
|         for (sync in settingsActivity.syncManager.services) { | ||||
|             val pref = SyncPreference(themedContext).apply { | ||||
|                 isPersistent = false | ||||
|                 title = sync.name | ||||
|                 key = sync.id.toString() | ||||
|                 dialogLayoutResource = R.layout.pref_account_login | ||||
|             } | ||||
|  | ||||
|             syncCategory.addPreference(pref) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun getSourcesWithLogin(): List<Source> { | ||||
|         return settingsActivity.sourceManager.sources.filter { it.isLoginRequired } | ||||
|     } | ||||
|  | ||||
|     override fun onDisplayPreferenceDialog(preference: Preference) { | ||||
|         if (preference is SourcePreference) { | ||||
|             val fragment = SourceLoginDialog.newInstance(preference) | ||||
|             fragment.setTargetFragment(this, 0) | ||||
|             fragment.show(childFragmentManager, null) | ||||
|         } else if (preference is SyncPreference) { | ||||
|             val fragment = MangaSyncLoginDialog.newInstance(preference) | ||||
|             fragment.setTargetFragment(this, 0) | ||||
|             fragment.show(childFragmentManager, null) | ||||
|         } else { | ||||
|             super.onDisplayPreferenceDialog(preference) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     class SourcePreference(context: Context) : DialogPreference(context) {} | ||||
|  | ||||
|     class SyncPreference(context: Context) : DialogPreference(context) {} | ||||
|  | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| package eu.kanade.tachiyomi.ui.setting | ||||
|  | ||||
| import android.os.Bundle | ||||
| import android.support.v7.preference.PreferenceFragmentCompat | ||||
| import android.support.v14.preference.PreferenceFragment | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.cache.ChapterCache | ||||
| import eu.kanade.tachiyomi.data.database.DatabaseHelper | ||||
| @@ -28,19 +28,19 @@ class SettingsActivity : BaseActivity() { | ||||
|         setupToolbar(toolbar) | ||||
|  | ||||
|         if (savedState == null) { | ||||
|             supportFragmentManager.beginTransaction() | ||||
|                     .replace(R.id.settings_content,SettingsMainFragment()) | ||||
|             fragmentManager.beginTransaction() | ||||
|                     .replace(R.id.settings_content, SettingsMainFragment()) | ||||
|                     .commit() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun onBackPressed() { | ||||
|         if (!supportFragmentManager.popBackStackImmediate()) { | ||||
|         if (!fragmentManager.popBackStackImmediate()) { | ||||
|             super.onBackPressed() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     class SettingsMainFragment : PreferenceFragmentCompat() { | ||||
|     class SettingsMainFragment : PreferenceFragment() { | ||||
|  | ||||
|         override fun onCreatePreferences(savedState: Bundle?, s: String?) { | ||||
|             addPreferencesFromResource(R.xml.pref_main) | ||||
| @@ -57,8 +57,12 @@ class SettingsActivity : BaseActivity() { | ||||
|                 SettingsDownloadsFragment.newInstance(R.xml.pref_downloads, R.string.pref_category_downloads) | ||||
|             } | ||||
|  | ||||
|             registerSubpreference(R.string.pref_category_accounts_key) { | ||||
|                 SettingsAccountsFragment.newInstance(R.xml.pref_accounts, R.string.pref_category_accounts) | ||||
|             registerSubpreference(R.string.pref_category_sources_key) { | ||||
|                 SettingsSourcesFragment.newInstance(R.xml.pref_sources, R.string.pref_category_sources) | ||||
|             } | ||||
|  | ||||
|             registerSubpreference(R.string.pref_category_sync_key) { | ||||
|                 SettingsSyncFragment.newInstance(R.xml.pref_sync, R.string.pref_category_sync) | ||||
|             } | ||||
|  | ||||
|             registerSubpreference(R.string.pref_category_advanced_key) { | ||||
| @@ -75,7 +79,7 @@ class SettingsActivity : BaseActivity() { | ||||
|             (activity as BaseActivity).setToolbarTitle(getString(R.string.label_settings)) | ||||
|         } | ||||
|  | ||||
|         private fun registerSubpreference(preferenceResource: Int, func: () -> PreferenceFragmentCompat) { | ||||
|         private fun registerSubpreference(preferenceResource: Int, func: () -> PreferenceFragment) { | ||||
|             findPreference(getString(preferenceResource)).setOnPreferenceClickListener { | ||||
|                 val fragment = func() | ||||
|                 fragmentManager.beginTransaction() | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| package eu.kanade.tachiyomi.ui.setting | ||||
|  | ||||
| import android.os.Bundle | ||||
| import android.support.v7.preference.PreferenceFragmentCompat | ||||
| import android.support.v14.preference.PreferenceFragment | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
|  | ||||
| open class SettingsNestedFragment : PreferenceFragmentCompat() { | ||||
| open class SettingsNestedFragment : PreferenceFragment() { | ||||
|  | ||||
|     companion object { | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,88 @@ | ||||
| package eu.kanade.tachiyomi.ui.setting | ||||
|  | ||||
| import android.content.Intent | ||||
| import android.os.Bundle | ||||
| import android.support.v14.preference.MultiSelectListPreference | ||||
| import android.support.v7.preference.Preference | ||||
| import android.support.v7.preference.PreferenceGroup | ||||
| import android.view.View | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.data.preference.getOrDefault | ||||
| import eu.kanade.tachiyomi.data.source.base.Source | ||||
| import eu.kanade.tachiyomi.data.source.getLanguages | ||||
| import eu.kanade.tachiyomi.widget.preference.LoginPreference | ||||
| import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog | ||||
| import rx.Subscription | ||||
|  | ||||
| class SettingsSourcesFragment : SettingsNestedFragment() { | ||||
|  | ||||
|     companion object { | ||||
|         const val SOURCE_CHANGE_REQUEST = 120 | ||||
|  | ||||
|         fun newInstance(resourcePreference: Int, resourceTitle: Int): SettingsNestedFragment { | ||||
|             val fragment = SettingsSourcesFragment() | ||||
|             fragment.setArgs(resourcePreference, resourceTitle) | ||||
|             return fragment | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     val languagesPref by lazy { findPreference("pref_source_languages") as MultiSelectListPreference } | ||||
|     val sourcesPref by lazy { findPreference("pref_sources") as PreferenceGroup } | ||||
|  | ||||
|     var languagesSubscription: Subscription? = null | ||||
|  | ||||
|     override fun onViewCreated(view: View, savedState: Bundle?) { | ||||
|         val langs = getLanguages() | ||||
|  | ||||
|         val entryKeys = langs.map { it.code } | ||||
|         languagesPref.entries = langs.map { it.lang }.toTypedArray() | ||||
|         languagesPref.entryValues = entryKeys.toTypedArray() | ||||
|         languagesPref.values = preferences.enabledLanguages().getOrDefault() | ||||
|  | ||||
|         languagesSubscription = preferences.enabledLanguages().asObservable() | ||||
|                 .subscribe { languages -> | ||||
|                     sourcesPref.removeAll() | ||||
|  | ||||
|                     val enabledSources = settingsActivity.sourceManager.getSources() | ||||
|                             .filter { it.lang.code in languages } | ||||
|  | ||||
|                     for (source in enabledSources) { | ||||
|                         if (source.isLoginRequired) { | ||||
|                             val pref = createSource(source) | ||||
|                             sourcesPref.addPreference(pref) | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     // Hide category if it doesn't have any child | ||||
|                     sourcesPref.isVisible = sourcesPref.preferenceCount > 0 | ||||
|                 } | ||||
|     } | ||||
|  | ||||
|     override fun onDestroyView() { | ||||
|         languagesSubscription?.unsubscribe() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
|  | ||||
|     fun createSource(source: Source): Preference { | ||||
|         return LoginPreference(preferenceManager.context).apply { | ||||
|             key = PreferencesHelper.SOURCE_ACCOUNT_USERNAME + source.id | ||||
|             title = source.visibleName | ||||
|  | ||||
|             setOnPreferenceClickListener { | ||||
|                 val fragment = SourceLoginDialog.newInstance(source) | ||||
|                 fragment.setTargetFragment(this@SettingsSourcesFragment, SOURCE_CHANGE_REQUEST) | ||||
|                 fragment.show(childFragmentManager, null) | ||||
|                 true | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | ||||
|         if (requestCode == SOURCE_CHANGE_REQUEST) { | ||||
|             val pref = findPreference(PreferencesHelper.SOURCE_ACCOUNT_USERNAME + resultCode) as? LoginPreference | ||||
|             pref?.notifyChanged() | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| package eu.kanade.tachiyomi.ui.setting | ||||
|  | ||||
| import android.content.Intent | ||||
| import android.os.Bundle | ||||
| import android.support.v7.preference.PreferenceCategory | ||||
| import android.view.View | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.widget.preference.LoginPreference | ||||
| import eu.kanade.tachiyomi.widget.preference.MangaSyncLoginDialog | ||||
|  | ||||
| class SettingsSyncFragment : SettingsNestedFragment() { | ||||
|  | ||||
|     companion object { | ||||
|         const val SYNC_CHANGE_REQUEST = 121 | ||||
|  | ||||
|         fun newInstance(resourcePreference: Int, resourceTitle: Int): SettingsNestedFragment { | ||||
|             val fragment = SettingsSyncFragment() | ||||
|             fragment.setArgs(resourcePreference, resourceTitle) | ||||
|             return fragment | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     val syncCategory by lazy { findPreference("pref_category_manga_sync_accounts") as PreferenceCategory } | ||||
|  | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         val themedContext = preferenceManager.context | ||||
|  | ||||
|         for (sync in settingsActivity.syncManager.services) { | ||||
|             val pref = LoginPreference(themedContext).apply { | ||||
|                 key = PreferencesHelper.MANGASYNC_ACCOUNT_USERNAME + sync.id | ||||
|                 title = sync.name | ||||
|  | ||||
|                 setOnPreferenceClickListener { | ||||
|                     val fragment = MangaSyncLoginDialog.newInstance(sync) | ||||
|                     fragment.setTargetFragment(this@SettingsSyncFragment, SYNC_CHANGE_REQUEST) | ||||
|                     fragment.show(childFragmentManager, null) | ||||
|                     true | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             syncCategory.addPreference(pref) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | ||||
|         if (requestCode == SYNC_CHANGE_REQUEST) { | ||||
|             val pref = findPreference(PreferencesHelper.MANGASYNC_ACCOUNT_USERNAME + resultCode) as? LoginPreference | ||||
|             pref?.notifyChanged() | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,15 +1,15 @@ | ||||
| package eu.kanade.tachiyomi.widget.preference | ||||
|  | ||||
| import android.os.Bundle | ||||
| import android.support.v14.preference.PreferenceDialogFragment | ||||
| import android.support.v7.preference.Preference | ||||
| import android.support.v7.preference.PreferenceDialogFragmentCompat | ||||
| import android.view.View | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.data.preference.getOrDefault | ||||
| import eu.kanade.tachiyomi.ui.setting.SettingsActivity | ||||
| import kotlinx.android.synthetic.main.pref_library_columns.view.* | ||||
|  | ||||
| class LibraryColumnsDialog : PreferenceDialogFragmentCompat() { | ||||
| class LibraryColumnsDialog : PreferenceDialogFragment() { | ||||
|  | ||||
|     companion object { | ||||
|  | ||||
|   | ||||
| @@ -1,18 +1,23 @@ | ||||
| package eu.kanade.tachiyomi.widget.preference | ||||
|  | ||||
| import android.support.v7.app.AlertDialog | ||||
| import android.support.v7.preference.PreferenceDialogFragmentCompat | ||||
| import android.app.Dialog | ||||
| import android.app.DialogFragment | ||||
| import android.content.DialogInterface | ||||
| import android.content.Intent | ||||
| import android.os.Bundle | ||||
| import android.text.Editable | ||||
| import android.text.TextWatcher | ||||
| import android.text.method.PasswordTransformationMethod | ||||
| import android.view.View | ||||
| import com.afollestad.materialdialogs.MaterialDialog | ||||
| import com.dd.processbutton.iml.ActionProcessButton | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.ui.setting.SettingsActivity | ||||
| import kotlinx.android.synthetic.main.pref_account_login.view.* | ||||
| import rx.Subscription | ||||
|  | ||||
| abstract class LoginDialogPreference : PreferenceDialogFragmentCompat() { | ||||
| abstract class LoginDialogPreference : DialogFragment() { | ||||
|  | ||||
|     var v: View? = null | ||||
|         private set | ||||
| @@ -22,13 +27,18 @@ abstract class LoginDialogPreference : PreferenceDialogFragmentCompat() { | ||||
|  | ||||
|     var requestSubscription: Subscription? = null | ||||
|  | ||||
|     override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) { | ||||
|         // Hide positive button | ||||
|         builder.setPositiveButton("", this) | ||||
|     override fun onCreateDialog(savedState: Bundle?): Dialog { | ||||
|         val dialog = MaterialDialog.Builder(activity) | ||||
|                 .customView(R.layout.pref_account_login, false) | ||||
|                 .negativeText(android.R.string.cancel) | ||||
|                 .build(); | ||||
|  | ||||
|         onViewCreated(dialog.view, savedState) | ||||
|  | ||||
|         return dialog | ||||
|     } | ||||
|  | ||||
|     override fun onBindDialogView(view: View) { | ||||
|         super.onBindDialogView(view) | ||||
|     override fun onViewCreated(view: View, savedState: Bundle?) { | ||||
|         v = view.apply { | ||||
|             show_password.setOnCheckedChangeListener { v, isChecked -> | ||||
|                 if (isChecked) | ||||
| @@ -59,10 +69,16 @@ abstract class LoginDialogPreference : PreferenceDialogFragmentCompat() { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     override fun onDialogClosed(positiveResult: Boolean) { | ||||
|     override fun onPause() { | ||||
|         super.onPause() | ||||
|         requestSubscription?.unsubscribe() | ||||
|     } | ||||
|  | ||||
|     override fun onDismiss(dialog: DialogInterface) { | ||||
|         super.onDismiss(dialog) | ||||
|         targetFragment?.onActivityResult(targetRequestCode, arguments.getInt("key"), Intent()) | ||||
|     } | ||||
|  | ||||
|     protected abstract fun checkLogin() | ||||
|  | ||||
|     protected abstract fun setCredentialsOnView(view: View) | ||||
|   | ||||
| @@ -0,0 +1,34 @@ | ||||
| package eu.kanade.tachiyomi.widget.preference | ||||
|  | ||||
| import android.content.Context | ||||
| import android.support.v4.content.ContextCompat | ||||
| import android.support.v7.preference.Preference | ||||
| import android.support.v7.preference.PreferenceViewHolder | ||||
| import android.util.AttributeSet | ||||
| import eu.kanade.tachiyomi.R | ||||
| import kotlinx.android.synthetic.main.preference_widget_imageview.view.* | ||||
|  | ||||
| class LoginPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : | ||||
|         Preference(context, attrs) { | ||||
|  | ||||
|     init { | ||||
|         widgetLayoutResource = R.layout.preference_widget_imageview | ||||
|     } | ||||
|  | ||||
|     override fun onBindViewHolder(holder: PreferenceViewHolder) { | ||||
|         super.onBindViewHolder(holder) | ||||
|  | ||||
|         with(holder.itemView.image_view) { | ||||
|             if (getPersistedString("").isNullOrEmpty()) { | ||||
|                 setImageResource(android.R.color.transparent) | ||||
|             } else { | ||||
|                 setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_done_green_24dp)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override public fun notifyChanged() { | ||||
|         super.notifyChanged() | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,8 +1,6 @@ | ||||
| package eu.kanade.tachiyomi.widget.preference | ||||
|  | ||||
| import android.content.DialogInterface | ||||
| import android.os.Bundle | ||||
| import android.support.v7.preference.Preference | ||||
| import android.view.View | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService | ||||
| @@ -16,10 +14,10 @@ class MangaSyncLoginDialog : LoginDialogPreference() { | ||||
|  | ||||
|     companion object { | ||||
|  | ||||
|         fun newInstance(preference: Preference): LoginDialogPreference { | ||||
|         fun newInstance(sync: MangaSyncService): LoginDialogPreference { | ||||
|             val fragment = MangaSyncLoginDialog() | ||||
|             val bundle = Bundle(1) | ||||
|             bundle.putString("key", preference.key) | ||||
|             bundle.putInt("key", sync.id) | ||||
|             fragment.arguments = bundle | ||||
|             return fragment | ||||
|         } | ||||
| @@ -30,12 +28,12 @@ class MangaSyncLoginDialog : LoginDialogPreference() { | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|  | ||||
|         val syncId = Integer.parseInt(arguments.getString("key")) | ||||
|         val syncId = arguments.getInt("key") | ||||
|         sync = (activity as SettingsActivity).syncManager.getService(syncId) | ||||
|     } | ||||
|  | ||||
|     override fun setCredentialsOnView(view: View) = with(view) { | ||||
|         accounts_login.text = getString(R.string.accounts_login_title, sync.name) | ||||
|         title.text = getString(R.string.login_title, sync.name) | ||||
|         username.setText(preferences.getMangaSyncUsername(sync)) | ||||
|         password.setText(preferences.getMangaSyncPassword(sync)) | ||||
|     } | ||||
| @@ -58,8 +56,6 @@ class MangaSyncLoginDialog : LoginDialogPreference() { | ||||
|                                     username.text.toString(), | ||||
|                                     password.text.toString()) | ||||
|  | ||||
|                             // Simulate a positive button click and dismiss the dialog | ||||
|                             onClick(dialog, DialogInterface.BUTTON_POSITIVE) | ||||
|                             dialog.dismiss() | ||||
|                             context.toast(R.string.login_success) | ||||
|                         } else { | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| package eu.kanade.tachiyomi.widget.preference | ||||
|  | ||||
| import android.content.DialogInterface | ||||
| import android.os.Bundle | ||||
| import android.support.v7.preference.Preference | ||||
| import android.view.View | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.source.base.Source | ||||
| @@ -16,10 +14,10 @@ class SourceLoginDialog : LoginDialogPreference() { | ||||
|  | ||||
|     companion object { | ||||
|  | ||||
|         fun newInstance(preference: Preference): LoginDialogPreference { | ||||
|         fun newInstance(source: Source): LoginDialogPreference { | ||||
|             val fragment = SourceLoginDialog() | ||||
|             val bundle = Bundle(1) | ||||
|             bundle.putString("key", preference.key) | ||||
|             bundle.putInt("key", source.id) | ||||
|             fragment.arguments = bundle | ||||
|             return fragment | ||||
|         } | ||||
| @@ -30,12 +28,12 @@ class SourceLoginDialog : LoginDialogPreference() { | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|  | ||||
|         val sourceId = Integer.parseInt(arguments.getString("key")) | ||||
|         val sourceId = arguments.getInt("key") | ||||
|         source = (activity as SettingsActivity).sourceManager.get(sourceId)!! | ||||
|     } | ||||
|  | ||||
|     override fun setCredentialsOnView(view: View) = with(view) { | ||||
|         accounts_login.text = getString(R.string.accounts_login_title, source.name) | ||||
|         title.text = getString(R.string.login_title, source.visibleName) | ||||
|         username.setText(preferences.getSourceUsername(source)) | ||||
|         password.setText(preferences.getSourcePassword(source)) | ||||
|     } | ||||
| @@ -58,8 +56,6 @@ class SourceLoginDialog : LoginDialogPreference() { | ||||
|                                     username.text.toString(), | ||||
|                                     password.text.toString()) | ||||
|  | ||||
|                             // Simulate a positive button click and dismiss the dialog | ||||
|                             onClick(dialog, DialogInterface.BUTTON_POSITIVE) | ||||
|                             dialog.dismiss() | ||||
|                             context.toast(R.string.login_success) | ||||
|                         } else { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user