diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7e221bce1..e18e81392 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,7 +23,9 @@ android:theme="@style/AppTheme" android:usesCleartextTraffic="true" tools:ignore="UnusedAttribute"> - + @@ -32,12 +34,16 @@ android:name="android.app.default_searchable" android:value=".ui.search.SearchActivity" /> - + - + @@ -50,13 +56,19 @@ android:label="@string/settings" /> - + + { + val url = HttpUrl.Builder() + .scheme(SCHEME_HTTP) + .host(domain) + .build() + return cookieJar.loadForRequest(url) + } + + fun copyCookies(oldDomain: String, newDomain: String) { + val url = HttpUrl.Builder() + .scheme(SCHEME_HTTP) + .host(oldDomain) + val cookies = cookieJar.loadForRequest(url.build()) + url.host(newDomain) + cookieJar.saveFromResponse(url.build(), cookies) + } + private companion object { private const val SCHEME_HTTP = "http" diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt index 27f923937..76f774bc8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt @@ -38,6 +38,7 @@ abstract class BaseFragment : Fragment(), OnApplyWindowInsetsLi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + lastInsets = Insets.NONE ViewCompat.setOnApplyWindowInsetsListener(view, this) } diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt b/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt index 4a666d1c7..f39da5fb5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt +++ b/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt @@ -1,10 +1,8 @@ package org.koitharu.kotatsu.browser import android.graphics.Bitmap -import android.webkit.WebResourceResponse import android.webkit.WebView import okhttp3.OkHttpClient -import okhttp3.Request import org.koin.core.component.KoinComponent import org.koin.core.component.inject import org.koitharu.kotatsu.core.network.WebViewClientCompat @@ -27,19 +25,4 @@ class BrowserClient(private val callback: BrowserCallback) : WebViewClientCompat super.onPageCommitVisible(view, url) callback.onTitleChanged(view.title.orEmpty(), url) } - - override fun shouldInterceptRequestCompat(view: WebView, url: String): WebResourceResponse? { - return runCatching { - val request = Request.Builder() - .url(url) - .build() - val response = okHttp.newCall(request).execute() - val ct = response.body?.contentType() - WebResourceResponse( - "${ct?.type}/${ct?.subtype}", - ct?.charset()?.name() ?: "utf-8", - response.body?.byteStream() - ) - }.getOrNull() - } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaFilter.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaFilter.kt index 68a3b5174..814c00571 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaFilter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaFilter.kt @@ -5,6 +5,6 @@ import kotlinx.parcelize.Parcelize @Parcelize data class MangaFilter( - val sortOrder: SortOrder, - val tag: MangaTag? + val sortOrder: SortOrder?, + val tag: MangaTag?, ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepositoryAuthProvider.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepositoryAuthProvider.kt new file mode 100644 index 000000000..16cc5e39f --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepositoryAuthProvider.kt @@ -0,0 +1,8 @@ +package org.koitharu.kotatsu.core.parser + +interface MangaRepositoryAuthProvider { + + val authUrl: String + + fun isAuthorized(): Boolean +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt index 6ee3d0747..7a6036d06 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt @@ -27,5 +27,6 @@ interface SourceSettings { const val KEY_DOMAIN = "domain" const val KEY_USE_SSL = "ssl" + const val KEY_AUTH = "auth" } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt index b0b32096a..e7fe78058 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt @@ -7,7 +7,6 @@ import org.koitharu.kotatsu.core.model.MangaFilter import org.koitharu.kotatsu.core.model.MangaTag import org.koitharu.kotatsu.core.model.SortOrder import java.util.* -import kotlin.collections.ArrayList class FilterAdapter( sortOrders: List = emptyList(), @@ -19,7 +18,7 @@ class FilterAdapter( private val sortOrders = ArrayList(sortOrders) private val tags = ArrayList(Collections.singletonList(null) + tags) - private var currentState = state ?: MangaFilter(sortOrders.first(), null) + private var currentState = state ?: MangaFilter(sortOrders.firstOrNull(), null) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { VIEW_TYPE_SORT -> FilterSortHolder(parent).apply { diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt index 1991e2c0e..844cbcbbc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt @@ -61,7 +61,7 @@ class LocalListViewModel( launchLoadingJob(Dispatchers.Default) { try { listError.value = null - mangaList.value = repository.getList(0) + mangaList.value = repository.getList(0, tags = null) } catch (e: Throwable) { listError.value = e } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/SimpleSettingsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/SimpleSettingsActivity.kt index 1c62b2cce..0113bb475 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/SimpleSettingsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/SimpleSettingsActivity.kt @@ -3,16 +3,19 @@ package org.koitharu.kotatsu.reader.ui import android.content.Context import android.content.Intent import android.os.Bundle +import android.os.Parcelable import androidx.core.graphics.Insets import androidx.core.view.updatePadding import androidx.fragment.app.commit import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.databinding.ActivitySettingsSimpleBinding import org.koitharu.kotatsu.settings.MainSettingsFragment import org.koitharu.kotatsu.settings.NetworkSettingsFragment import org.koitharu.kotatsu.settings.ReaderSettingsFragment +import org.koitharu.kotatsu.settings.SourceSettingsFragment class SimpleSettingsActivity : BaseActivity() { @@ -25,6 +28,9 @@ class SimpleSettingsActivity : BaseActivity() { R.id.container, when (intent?.action) { Intent.ACTION_MANAGE_NETWORK_USAGE -> NetworkSettingsFragment() ACTION_READER -> ReaderSettingsFragment() + ACTION_SOURCE -> SourceSettingsFragment.newInstance( + intent.getParcelableExtra(EXTRA_SOURCE) ?: MangaSource.LOCAL + ) else -> MainSettingsFragment() } ) @@ -43,9 +49,17 @@ class SimpleSettingsActivity : BaseActivity() { private const val ACTION_READER = "${BuildConfig.APPLICATION_ID}.action.MANAGE_READER_SETTINGS" + private const val ACTION_SOURCE = + "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCE_SETTINGS" + private const val EXTRA_SOURCE = "source" fun newReaderSettingsIntent(context: Context) = Intent(context, SimpleSettingsActivity::class.java) .setAction(ACTION_READER) + + fun newSourceSettingsIntent(context: Context, source: MangaSource) = + Intent(context, SimpleSettingsActivity::class.java) + .setAction(ACTION_SOURCE) + .putExtra(EXTRA_SOURCE, source as Parcelable) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt index 1c5004eb4..2ecb7f7bf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt @@ -1,10 +1,15 @@ package org.koitharu.kotatsu.remotelist.ui +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.parameter.parametersOf +import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.MangaFilter import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.list.ui.MangaListFragment +import org.koitharu.kotatsu.reader.ui.SimpleSettingsActivity import org.koitharu.kotatsu.utils.ext.parcelableArgument import org.koitharu.kotatsu.utils.ext.withArgs @@ -29,6 +34,26 @@ class RemoteListFragment : MangaListFragment() { super.onFilterChanged(filter) } + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + super.onCreateOptionsMenu(menu, inflater) + inflater.inflate(R.menu.opt_list_remote, menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.action_source_settings -> { + startActivity( + SimpleSettingsActivity.newSourceSettingsIntent( + context ?: return false, + source, + ) + ) + true + } + else -> super.onOptionsItemSelected(item) + } + } + companion object { private const val ARG_SOURCE = "provider" diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt index b344b2bda..aaf6ccaa3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt @@ -90,6 +90,9 @@ class RemoteListViewModel( } hasNextPage.value = list.isNotEmpty() } catch (e: Throwable) { + if (BuildConfig.DEBUG) { + e.printStackTrace() + } listError.value = e } } diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt index 193817c33..35df96c82 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt @@ -12,7 +12,6 @@ import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.* import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct -import java.util.* class SearchViewModel( private val repository: MangaRepository, @@ -74,6 +73,7 @@ class SearchViewModel( listError.value = null val list = repository.getList( offset = if (append) mangaList.value?.size ?: 0 else 0, + tags = null, query = query ) if (!append) { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt index 8380e414f..99ec51e9c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt @@ -76,15 +76,7 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach true } AppSettings.KEY_COOKIES_CLEAR -> { - viewLifecycleScope.launch { - val cookieJar = get() - cookieJar.clear() - Snackbar.make( - listView ?: return@launch, - R.string.cookies_cleared, - Snackbar.LENGTH_SHORT - ).show() - } + clearCookies() true } AppSettings.KEY_SEARCH_HISTORY_CLEAR -> { @@ -144,4 +136,22 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach } }.show() } + + private fun clearCookies() { + AlertDialog.Builder(context ?: return) + .setTitle(R.string.clear_cookies) + .setMessage(R.string.text_clear_cookies_prompt) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(R.string.clear) { _, _ -> + viewLifecycleScope.launch { + val cookieJar = get() + cookieJar.clear() + Snackbar.make( + listView ?: return@launch, + R.string.cookies_cleared, + Snackbar.LENGTH_SHORT + ).show() + } + }.show() + } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt index 4bccaf8e2..da9115e80 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt @@ -9,8 +9,10 @@ import androidx.preference.PreferenceFragmentCompat import androidx.preference.TwoStatePreference import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.MangaSource +import org.koitharu.kotatsu.core.parser.MangaRepositoryAuthProvider import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.prefs.SourceSettings +import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity import org.koitharu.kotatsu.settings.utils.EditTextBindListener import org.koitharu.kotatsu.settings.utils.EditTextDefaultSummaryProvider import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf @@ -20,6 +22,7 @@ import org.koitharu.kotatsu.utils.ext.withArgs class SourceSettingsFragment : PreferenceFragmentCompat() { private val source by parcelableArgument(EXTRA_SOURCE) + private var repository: RemoteMangaRepository? = null override fun onResume() { super.onResume() @@ -29,6 +32,7 @@ class SourceSettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { preferenceManager.sharedPreferencesName = source.name val repo = mangaRepositoryOf(source) as? RemoteMangaRepository ?: return + repository = repo addPreferencesFromResource(R.xml.pref_source) val screen = preferenceScreen val prefsMap = ArrayMap(screen.preferenceCount) @@ -41,13 +45,32 @@ class SourceSettingsFragment : PreferenceFragmentCompat() { initPreferenceWithDefaultValue(pref, defValue) } } + findPreference(SourceSettings.KEY_AUTH)?.run { + isVisible = repo is MangaRepositoryAuthProvider + isEnabled = (repo as? MangaRepositoryAuthProvider)?.isAuthorized() == false + } + } + + override fun onPreferenceTreeClick(preference: Preference?): Boolean { + return when (preference?.key) { + SourceSettings.KEY_AUTH -> { + startActivity( + SourceAuthActivity.newIntent( + context ?: return false, + source, + ) + ) + true + } + else -> super.onPreferenceTreeClick(preference) + } } private fun initPreferenceWithDefaultValue(preference: Preference, defaultValue: Any) { - when(preference) { + when (preference) { is EditTextPreference -> { preference.summaryProvider = EditTextDefaultSummaryProvider(defaultValue.toString()) - when(preference.key) { + when (preference.key) { SourceSettings.KEY_DOMAIN -> preference.setOnBindEditTextListener( EditTextBindListener( EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_URI, diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt new file mode 100644 index 000000000..896c92780 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt @@ -0,0 +1,114 @@ +package org.koitharu.kotatsu.settings.sources.auth + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.Parcelable +import android.view.MenuItem +import android.widget.Toast +import androidx.core.graphics.Insets +import androidx.core.view.isVisible +import androidx.core.view.updatePadding +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.browser.BrowserCallback +import org.koitharu.kotatsu.browser.BrowserClient +import org.koitharu.kotatsu.core.model.MangaSource +import org.koitharu.kotatsu.core.parser.MangaRepositoryAuthProvider +import org.koitharu.kotatsu.databinding.ActivityBrowserBinding +import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf + +class SourceAuthActivity : BaseActivity(), BrowserCallback { + + private lateinit var repository: MangaRepositoryAuthProvider + + @SuppressLint("SetJavaScriptEnabled") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(ActivityBrowserBinding.inflate(layoutInflater)) + val source = intent?.getParcelableExtra(EXTRA_SOURCE) + if (source == null) { + finish() + return + } + repository = mangaRepositoryOf(source) as? MangaRepositoryAuthProvider ?: run { + Toast.makeText( + this, + getString(R.string.auth_not_supported_by, source.title), + Toast.LENGTH_SHORT + ).show() + finishAfterTransition() + return + } + supportActionBar?.run { + setDisplayHomeAsUpEnabled(true) + setHomeAsUpIndicator(R.drawable.ic_cross) + } + with(binding.webView.settings) { + javaScriptEnabled = true + } + binding.webView.webViewClient = BrowserClient(this) + val url = repository.authUrl + onTitleChanged( + source.title, + getString(R.string.loading_) + ) + binding.webView.loadUrl(url) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { + android.R.id.home -> { + binding.webView.stopLoading() + finishAfterTransition() + true + } + else -> super.onOptionsItemSelected(item) + } + + override fun onBackPressed() { + if (binding.webView.canGoBack()) { + binding.webView.goBack() + } else { + super.onBackPressed() + } + } + + override fun onPause() { + binding.webView.onPause() + super.onPause() + } + + override fun onResume() { + super.onResume() + binding.webView.onResume() + } + + override fun onLoadingStateChanged(isLoading: Boolean) { + binding.progressBar.isVisible = isLoading + if (!isLoading && repository.isAuthorized()) { + Toast.makeText(this, R.string.auth_complete, Toast.LENGTH_SHORT).show() + finishAfterTransition() + } + } + + override fun onTitleChanged(title: CharSequence, subtitle: CharSequence?) { + this.title = title + supportActionBar?.subtitle = subtitle + } + + override fun onWindowInsetsChanged(insets: Insets) { + binding.appbar.updatePadding(top = insets.top) + binding.webView.updatePadding(bottom = insets.bottom) + } + + companion object { + + private const val EXTRA_SOURCE = "source" + + fun newIntent(context: Context, source: MangaSource): Intent { + return Intent(context, SourceAuthActivity::class.java) + .putExtra(EXTRA_SOURCE, source as Parcelable) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/menu/opt_list_remote.xml b/app/src/main/res/menu/opt_list_remote.xml new file mode 100644 index 000000000..deb531840 --- /dev/null +++ b/app/src/main/res/menu/opt_list_remote.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 29428323b..35be37286 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -213,24 +213,27 @@ Другие Описание Языки - Добро пожаловать - Вы действительно хотите удалить все недавние поисковые запросы? Это действие не может быть отменено. - Резервная копия успешно сохранена - Некоторые производители могут изменять поведение системы, нарушая работу фоновых задач. - Подробнее - В очереди - На данный момент нет активных загрузок - Глава отсутствует - Эта глава отсутствует на вашем устройстве. Скачайте или прочитайте её онлайн. - Помочь с переводом приложения - Перевод - Автор - Тема на 4PDA - Обратная связь - Поддержать разработчика - Если вам нравится это приложение, вы можете помочь финансово с помощью ЮMoney (бывш. Яндекс.Деньги) - Благодарности - Эти люди помогают Kotatsu стать лучше! - Авторские права и лицензии - Лицензия + Добро пожаловать + Вы действительно хотите удалить все недавние поисковые запросы? Это действие не может быть отменено. + Резервная копия успешно сохранена + Некоторые производители могут изменять поведение системы, нарушая работу фоновых задач. + Подробнее + В очереди + На данный момент нет активных загрузок + Глава отсутствует + Эта глава отсутствует на вашем устройстве. Скачайте или прочитайте её онлайн. + Помочь с переводом приложения + Перевод + Автор + Тема на 4PDA + Обратная связь + Поддержать разработчика + Если вам нравится это приложение, вы можете помочь финансово с помощью ЮMoney (бывш. Яндекс.Деньги) + Благодарности + Эти люди помогают Kotatsu стать лучше! + Авторские права и лицензии + Лицензия + Авторизация выполнена + Авторизация в %s не поддерживается + Вы выйдете из всех источников, в которых Вы авторизованы \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6566b5749..f82f4b5d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -216,24 +216,27 @@ Do you really want to remove all recent search queries? This action cannot be undone. Other Languages - Welcome - Description - Backup saved successfully - Some manufacturers can change the system behavior, which may breaks background tasks. - Read more - Queued - There are currently no active downloads - This chapter is missing on your device. Download or read it online. - Chapter is missing - Translate this app - Translation - Author - Feedback - Topic on 4PDA - Support the developer - If you like this app, you can help financially through Yoomoney (ex. Yandex.Money) - Gratitudes - These people make Kotatsu become better! - Copyright & Licenses - License + Welcome + Description + Backup saved successfully + Some manufacturers can change the system behavior, which may breaks background tasks. + Read more + Queued + There are currently no active downloads + This chapter is missing on your device. Download or read it online. + Chapter is missing + Translate this app + Translation + Author + Feedback + Topic on 4PDA + Support the developer + If you like this app, you can help financially through Yoomoney (ex. Yandex.Money) + Gratitudes + These people make Kotatsu become better! + Copyright & Licenses + License + Authorization complete + Authorization on %s is not supported + You will be logged out from all sources that you are authorized in \ No newline at end of file diff --git a/app/src/main/res/xml/pref_source.xml b/app/src/main/res/xml/pref_source.xml index fa59bb8f9..6e773ce26 100644 --- a/app/src/main/res/xml/pref_source.xml +++ b/app/src/main/res/xml/pref_source.xml @@ -14,4 +14,11 @@ android:title="@string/use_ssl" app:iconSpaceReserved="false" /> + + \ No newline at end of file