diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java index f182f2e4f7..3b436c72f1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java @@ -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 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 c5adab4616..965a9f8984 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 @@ -11,9 +11,7 @@ import eu.kanade.tachiyomi.data.source.base.Source import java.io.File import java.io.IOException -fun Preference.getOrDefault(): T { - return get() ?: defaultValue()!! -} +fun Preference.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> { + return rxPrefs.getStringSet(getKey(R.string.pref_source_languages), setOf("EN")) + } + fun getSourceUsername(source: Source): String { return prefs.getString(SOURCE_ACCOUNT_USERNAME + source.id, "") } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/Language.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/Language.kt new file mode 100644 index 0000000000..4c5b862e73 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/Language.kt @@ -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 = listOf(EN, RU) \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/SourceManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/SourceManager.kt index f002e3ef7c..ee1e98edf2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/SourceManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/SourceManager.kt @@ -11,7 +11,6 @@ import java.util.* open class SourceManager(private val context: Context) { val sourcesMap: HashMap - val sources: List 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 = ArrayList(sourcesMap.values) + } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/base/BaseSource.java b/app/src/main/java/eu/kanade/tachiyomi/data/source/base/BaseSource.java index 3410ae0416..6817c84e15 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/base/BaseSource.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/base/BaseSource.java @@ -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(); } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.java b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.java index 174a190069..f1610b1a73 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.java @@ -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(); diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.java b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.java index 50cbd1bf7a..f73477989d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.java @@ -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); diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.java b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.java index a7b16f41b1..d92efb985b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.java @@ -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, ""); diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.java b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.java index b545b7e8ec..43aa3ee4ce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.java @@ -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, ""); diff --git a/app/src/main/java/eu/kanade/tachiyomi/injection/component/AppComponent.java b/app/src/main/java/eu/kanade/tachiyomi/injection/component/AppComponent.java index 368d3dd70c..f05b164c05 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/injection/component/AppComponent.java +++ b/app/src/main/java/eu/kanade/tachiyomi/injection/component/AppComponent.java @@ -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); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt index 965f4e5ab2..cc2749fffa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt index 7fa42260ed..78b7f81273 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt @@ -168,7 +168,7 @@ class CatalogueFragment : BaseRxFragment(), 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(), 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() + }) } /** 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 index 7ad91ea812..c77acb19cb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt @@ -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() { /** * Enabled sources. */ - private val sources by lazy { sourceManager.sources } + val sources by lazy { getEnabledSources() } /** * Active source. @@ -188,6 +189,13 @@ class CataloguePresenter : BasePresenter() { } } + /** + * 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() { } /** - * 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 { - return sourceManager.sources + private fun getEnabledSources(): List { + 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}" } } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java index 6b259c0938..1c1e855f21 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java @@ -143,7 +143,7 @@ public class MangaInfoFragment extends BaseRxFragment { // If manga source is known update source TextView. if (mangaSource != null) { - source.setText(mangaSource.getName()); + source.setText(mangaSource.getVisibleName()); } // Update genres TextView. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAccountsFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAccountsFragment.kt deleted file mode 100644 index 52e4a16b59..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAccountsFragment.kt +++ /dev/null @@ -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 { - 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) {} - -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt index 2d97da924d..59486fbf6f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt @@ -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() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsNestedFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsNestedFragment.kt index 0eb1b3fccf..b2d44e1352 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsNestedFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsNestedFragment.kt @@ -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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSourcesFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSourcesFragment.kt new file mode 100644 index 0000000000..a5b5615e7a --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSourcesFragment.kt @@ -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() + } + } + +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSyncFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSyncFragment.kt new file mode 100644 index 0000000000..e6400f3396 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSyncFragment.kt @@ -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() + } + } + +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LibraryColumnsDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LibraryColumnsDialog.kt index 79f00efcf8..43dd099bc9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LibraryColumnsDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LibraryColumnsDialog.kt @@ -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 { 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 faec547718..e37ded4754 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 @@ -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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginPreference.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginPreference.kt new file mode 100644 index 0000000000..c2889443cb --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginPreference.kt @@ -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() + } + +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/MangaSyncLoginDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/MangaSyncLoginDialog.kt index 4780289940..02136ce7ec 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/MangaSyncLoginDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/MangaSyncLoginDialog.kt @@ -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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/SourceLoginDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/SourceLoginDialog.kt index f95ddc02c7..715e681acd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/SourceLoginDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/SourceLoginDialog.kt @@ -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 { diff --git a/app/src/main/res/drawable-xhdpi/bkg_shadow_img.9.png b/app/src/main/res/drawable-xhdpi/bkg_shadow_img.9.png deleted file mode 100644 index 6bd9c52050..0000000000 Binary files a/app/src/main/res/drawable-xhdpi/bkg_shadow_img.9.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_done_green_24dp.xml b/app/src/main/res/drawable/ic_done_green_24dp.xml new file mode 100644 index 0000000000..86e45f4a61 --- /dev/null +++ b/app/src/main/res/drawable/ic_done_green_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/item_chapter.xml b/app/src/main/res/layout/item_chapter.xml index c34d6dddae..0c3635b7ce 100644 --- a/app/src/main/res/layout/item_chapter.xml +++ b/app/src/main/res/layout/item_chapter.xml @@ -96,7 +96,7 @@ android:layout_alignParentTop="true" android:background="?android:selectableItemBackground" app:srcCompat="@drawable/ic_more_horiz_black_24dp"/> - + diff --git a/app/src/main/res/layout/pref_account_login.xml b/app/src/main/res/layout/pref_account_login.xml index 50e8baa594..e4a30d9a11 100644 --- a/app/src/main/res/layout/pref_account_login.xml +++ b/app/src/main/res/layout/pref_account_login.xml @@ -9,8 +9,8 @@ diff --git a/app/src/main/res/layout/preference_widget_imageview.xml b/app/src/main/res/layout/preference_widget_imageview.xml new file mode 100644 index 0000000000..626be8b310 --- /dev/null +++ b/app/src/main/res/layout/preference_widget_imageview.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index b1a0612817..c6174e94d5 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -2,10 +2,11 @@ pref_category_general_key pref_category_reader_key - pref_category_accounts_key + pref_category_sync_key pref_category_downloads_key pref_category_advanced_key pref_category_about_key + pref_category_sources_key pref_library_columns_dialog_key pref_library_columns_portrait_key @@ -35,6 +36,8 @@ pref_download_slots_key pref_download_only_over_wifi_key + pref_source_languages + pref_clear_chapter_cache_key pref_clear_database_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fb62107288..bff8953b04 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,8 +63,9 @@ General Reader - Accounts Downloads + Sources + Sync Advanced About @@ -124,13 +125,20 @@ Force portrait Force landscape - Downloads directory Simultaneous downloads Only download over Wi-Fi Custom directory + + Languages + Select the languages to show sources from + Accounts + + + Services + Clear chapter cache Used: %1$s @@ -150,7 +158,7 @@ - Login for %1$s + Login for %1$s Username Password Show password diff --git a/app/src/main/res/xml/pref_accounts.xml b/app/src/main/res/xml/pref_accounts.xml deleted file mode 100644 index 04aefb26d5..0000000000 --- a/app/src/main/res/xml/pref_accounts.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index 66c002a7aa..a05f27340d 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -21,15 +21,4 @@ android:title="@string/pref_update_only_non_completed" android:defaultValue="false"/> - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/pref_main.xml b/app/src/main/res/xml/pref_main.xml index aa657d50a2..35df586657 100644 --- a/app/src/main/res/xml/pref_main.xml +++ b/app/src/main/res/xml/pref_main.xml @@ -16,11 +16,16 @@ android:key="@string/pref_category_downloads_key" android:persistent="false" android:title="@string/pref_category_downloads" /> + + + android:title="@string/pref_category_sync" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/pref_sync.xml b/app/src/main/res/xml/pref_sync.xml new file mode 100644 index 0000000000..a41621dd71 --- /dev/null +++ b/app/src/main/res/xml/pref_sync.xml @@ -0,0 +1,22 @@ + + + + + + + + + + \ No newline at end of file