Merge pull request #209 from inorichi/source-languages

Support for sources from different languages
This commit is contained in:
inorichi 2016-03-10 16:23:09 +01:00
commit dc742f4b8d
36 changed files with 407 additions and 173 deletions

View File

@ -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

View File

@ -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, "")
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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();
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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, "");

View File

@ -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, "");

View File

@ -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);

View File

@ -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

View File

@ -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()
})
}
/**

View File

@ -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}" }
}
/**

View File

@ -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.

View File

@ -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) {}
}

View File

@ -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()

View File

@ -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 {

View File

@ -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()
}
}
}

View File

@ -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()
}
}
}

View File

@ -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 {

View File

@ -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)

View File

@ -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()
}
}

View File

@ -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 {

View File

@ -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 {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF4CAF50"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</vector>

View File

@ -96,7 +96,7 @@
android:layout_alignParentTop="true"
android:background="?android:selectableItemBackground"
app:srcCompat="@drawable/ic_more_horiz_black_24dp"/>
</RelativeLayout>

View File

@ -9,8 +9,8 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/accounts_login_title"
android:id="@+id/accounts_login"
android:text="@string/login_title"
android:id="@+id/title"
android:textStyle="bold"
android:textSize="16sp"
android:layout_gravity="center_horizontal" />

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ImageView>

View File

@ -2,10 +2,11 @@
<resources>
<string name="pref_category_general_key">pref_category_general_key</string>
<string name="pref_category_reader_key">pref_category_reader_key</string>
<string name="pref_category_accounts_key">pref_category_accounts_key</string>
<string name="pref_category_sync_key">pref_category_sync_key</string>
<string name="pref_category_downloads_key">pref_category_downloads_key</string>
<string name="pref_category_advanced_key">pref_category_advanced_key</string>
<string name="pref_category_about_key">pref_category_about_key</string>
<string name="pref_category_sources_key">pref_category_sources_key</string>
<string name="pref_library_columns_dialog_key">pref_library_columns_dialog_key</string>
<string name="pref_library_columns_portrait_key">pref_library_columns_portrait_key</string>
@ -35,6 +36,8 @@
<string name="pref_download_slots_key">pref_download_slots_key</string>
<string name="pref_download_only_over_wifi_key">pref_download_only_over_wifi_key</string>
<string name="pref_source_languages">pref_source_languages</string>
<string name="pref_clear_chapter_cache_key">pref_clear_chapter_cache_key</string>
<string name="pref_clear_database_key">pref_clear_database_key</string>

View File

@ -63,8 +63,9 @@
<!-- Subsections -->
<string name="pref_category_general">General</string>
<string name="pref_category_reader">Reader</string>
<string name="pref_category_accounts">Accounts</string>
<string name="pref_category_downloads">Downloads</string>
<string name="pref_category_sources">Sources</string>
<string name="pref_category_sync">Sync</string>
<string name="pref_category_advanced">Advanced</string>
<string name="pref_category_about">About</string>
@ -124,13 +125,20 @@
<string name="rotation_force_portrait">Force portrait</string>
<string name="rotation_force_landscape">Force landscape</string>
<!-- Downloads section -->
<string name="pref_download_directory">Downloads directory</string>
<string name="pref_download_slots">Simultaneous downloads</string>
<string name="pref_download_only_over_wifi">Only download over Wi-Fi</string>
<string name="custom_dir">Custom directory</string>
<!-- Sources section -->
<string name="languages">Languages</string>
<string name="languages_summary">Select the languages to show sources from</string>
<string name="accounts">Accounts</string>
<!-- Sync section -->
<string name="services">Services</string>
<!-- Advanced section -->
<string name="pref_clear_chapter_cache">Clear chapter cache</string>
<string name="used_cache">Used: %1$s</string>
@ -150,7 +158,7 @@
<!-- Login dialog -->
<string name="accounts_login_title">Login for %1$s</string>
<string name="login_title">Login for %1$s</string>
<string name="username">Username</string>
<string name="password">Password</string>
<string name="show_password">Show password</string>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:orderingFromXml="true">
<PreferenceCategory
android:key="pref_category_source_accounts"
android:title="Sources"
android:persistent="false"/>
<PreferenceCategory
android:key="pref_category_manga_sync_accounts"
android:title="Sync"
android:persistent="false"/>
</android.support.v7.preference.PreferenceScreen>

View File

@ -21,15 +21,4 @@
android:title="@string/pref_update_only_non_completed"
android:defaultValue="false"/>
<SwitchPreferenceCompat
android:key="@string/pref_auto_update_manga_sync_key"
android:title="@string/pref_auto_update_manga_sync"
android:defaultValue="true"/>
<SwitchPreferenceCompat
android:key="@string/pref_ask_update_manga_sync_key"
android:title="@string/pref_ask_update_manga_sync"
android:defaultValue="false"
android:dependency="@string/pref_auto_update_manga_sync_key"/>
</android.support.v7.preference.PreferenceScreen>

View File

@ -16,11 +16,16 @@
android:key="@string/pref_category_downloads_key"
android:persistent="false"
android:title="@string/pref_category_downloads" />
<Preference
android:key="@string/pref_category_sources_key"
android:persistent="false"
android:title="@string/pref_category_sources" />
<Preference
android:key="@string/pref_category_accounts_key"
android:key="@string/pref_category_sync_key"
android:persistent="false"
android:title="@string/pref_category_accounts" />
android:title="@string/pref_category_sync" />
<Preference
android:key="@string/pref_category_advanced_key"

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:orderingFromXml="true">
<MultiSelectListPreference
android:key="@string/pref_source_languages"
android:title="@string/languages"
android:summary="@string/languages_summary"/>
<PreferenceCategory
android:key="pref_sources"
android:persistent="false"
android:title="@string/accounts"/>
</android.support.v7.preference.PreferenceScreen>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:orderingFromXml="true">
<SwitchPreferenceCompat
android:key="@string/pref_auto_update_manga_sync_key"
android:title="@string/pref_auto_update_manga_sync"
android:defaultValue="true"/>
<SwitchPreferenceCompat
android:key="@string/pref_ask_update_manga_sync_key"
android:title="@string/pref_ask_update_manga_sync"
android:defaultValue="false"
android:dependency="@string/pref_auto_update_manga_sync_key"/>
<PreferenceCategory
android:key="pref_category_manga_sync_accounts"
android:title="@string/services"
android:persistent="false"/>
</android.support.v7.preference.PreferenceScreen>