Add migration system.

This commit is contained in:
NerdNumber9 2017-01-06 18:01:40 -05:00
parent cb73e55db1
commit 2b988c51ad
17 changed files with 498 additions and 152 deletions

View File

@ -132,6 +132,15 @@
android:scheme="https"/>
</intent-filter>
</activity>
<activity
android:name="exh.ui.migration.MigrationCompletionActivity"
android:label="Complete migration">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/json"/>
</intent-filter>
</activity>
</application>

View File

@ -9,6 +9,7 @@ import com.f2prateek.rx.preferences.RxSharedPreferences
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.Source
import eu.kanade.tachiyomi.data.track.TrackService
import exh.ui.migration.MigrationStatus
import java.io.File
fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!
@ -161,6 +162,10 @@ class PreferencesHelper(val context: Context) {
fun migrateLibraryAsked() = rxPrefs.getBoolean("ex_migrate_library", false)
fun migrationStatus() = rxPrefs.getInteger("migration_status", MigrationStatus.NOT_INITIALIZED)
fun finishMainActivity() = rxPrefs.getBoolean("finish_main_activity", false)
//EH Cookies
fun memberIdVal() = rxPrefs.getString("eh_ipb_member_id", null)
fun passHashVal() = rxPrefs.getString("eh_ipb_pass_hash", null)

View File

@ -120,7 +120,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
.searchSubject
.debounce(100L, TimeUnit.MILLISECONDS)
.subscribe { text -> //Debounce search (EH)
adapter.asyncSearchText = text.trim().toLowerCase()
adapter.asyncSearchText = text?.trim()?.toLowerCase()
adapter.updateDataSet()
}

View File

@ -25,7 +25,6 @@ class ChangelogDialogFragment : DialogFragment() {
preferences.lastVersionCode().set(BuildConfig.VERSION_CODE)
ChangelogDialogFragment().show(fm, "changelog")
// TODO better upgrades management
if (oldVersion == 0) return
if (oldVersion < 14) {
@ -39,6 +38,7 @@ class ChangelogDialogFragment : DialogFragment() {
// Delete internal chapter cache dir.
File(context.cacheDir, "chapter_disk_cache").deleteRecursively()
}
//TODO Review any other changes below
}
}
}

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.main
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.Fragment
@ -7,7 +8,6 @@ import android.support.v4.app.TaskStackBuilder
import android.support.v4.view.GravityCompat
import android.view.MenuItem
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.backup.BackupFragment
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
@ -18,18 +18,21 @@ import eu.kanade.tachiyomi.ui.library.LibraryFragment
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersFragment
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadFragment
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
import exh.ui.MetadataFetchDialog
import exh.ui.batchadd.BatchAddFragment
import exh.ui.migration.LibraryMigrationManager
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.toolbar.*
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import rx.Subscription
import uy.kohesive.injekt.injectLazy
class MainActivity : BaseActivity() {
val preferences: PreferencesHelper by injectLazy()
var finishSubscription: Subscription? = null
var dismissQueue = mutableListOf<DialogInterface>()
private val startScreenId by lazy {
when (preferences.startScreen()) {
1 -> R.id.nav_drawer_library
@ -88,15 +91,25 @@ class MainActivity : BaseActivity() {
ChangelogDialogFragment.show(this, preferences, supportFragmentManager)
// Migrate library if needed
Injekt.get<DatabaseHelper>().getLibraryMangas().asRxSingle().subscribe {
if(it.size > 0)
runOnUiThread {
MetadataFetchDialog().tryAskMigration(this)
}
LibraryMigrationManager(this, dismissQueue).askMigrationIfNecessary()
//Last part of migration requires finishing this activity
finishSubscription?.unsubscribe()
preferences.finishMainActivity().set(false)
finishSubscription = preferences.finishMainActivity().asObservable().subscribe {
if(it)
finish()
}
}
}
override fun onDestroy() {
super.onDestroy()
finishSubscription?.unsubscribe()
preferences.finishMainActivity().set(false)
dismissQueue.forEach { it.dismiss() }
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> drawer.openDrawer(GravityCompat.START)
@ -155,5 +168,6 @@ class MainActivity : BaseActivity() {
companion object {
private const val REQUEST_OPEN_SETTINGS = 200
const val FINALIZE_MIGRATION = "finalize_migration"
}
}

View File

@ -6,7 +6,7 @@ import android.support.v7.preference.XpPreferenceFragment
import android.view.View
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.plusAssign
import exh.ui.MetadataFetchDialog
import exh.ui.migration.MetadataFetchDialog
import exh.ui.login.LoginActivity
import net.xpece.android.support.preference.Preference
import net.xpece.android.support.preference.SwitchPreference

View File

@ -0,0 +1,263 @@
package exh.ui.migration
import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.text.Html
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.toast
import uy.kohesive.injekt.injectLazy
/**
* Guide to migrate thel ibrary between two TachiyomiEH apps
*/
class LibraryMigrationManager(val context: MainActivity,
val dismissQueue: MutableList<DialogInterface>? = null) {
val preferenceHelper: PreferencesHelper by injectLazy()
val databaseHelper: DatabaseHelper by injectLazy()
private fun mainTachiyomiEHActivity()
= context.packageManager.getLaunchIntentForPackage(TACHIYOMI_EH_PACKAGE)
fun askMigrationIfNecessary() {
//Check already migrated
val ms = preferenceHelper.migrationStatus().getOrDefault()
if(ms == MigrationStatus.COMPLETED) return
val ma = mainTachiyomiEHActivity()
//Old version not installed, migration not required
if(ma == null) {
preferenceHelper.migrationStatus().set(MigrationStatus.COMPLETED)
return
}
context.requestPermissionsOnMarshmallow()
if(ms == MigrationStatus.NOT_INITIALIZED) {
//We need migration
jumpToMigrationStep(MigrationStatus.NOTIFY_USER)
} else {
//Migration process already started, jump to step
jumpToMigrationStep(ms)
}
}
fun notifyUserMigration() {
redDialog()
.title("Migration necessary")
.content("Due to an unplanned technical error, this update could not be applied on top of the old app and was instead installed as a separate app!\n\n" +
"To keep your library/favorited galleries after this update, you must migrate it over from the old app.\n\n" +
"This migration process is not automatic, tap 'CONTINUE' to be guided through it.")
.positiveText("Continue")
.negativeText("Cancel")
.onPositive { materialDialog, dialogAction -> jumpToMigrationStep(MigrationStatus.OPEN_BACKUP_MENU) }
.onNegative { materialDialog, dialogAction -> warnUserMigration() }
.show()
}
fun warnUserMigration() {
redDialog()
.title("Are you sure?")
.content("You are cancelling the migration process! If you do not migrate your library, you will lose all of your favorited galleries!\n\n" +
"Press 'MIGRATE' to restart the migration process, press 'OK' if you still wish to cancel the migration process.")
.positiveText("Ok")
.negativeText("Migrate")
.onPositive { materialDialog, dialogAction -> completeMigration() }
.onNegative { materialDialog, dialogAction -> notifyUserMigration() }
.show()
}
fun openBackupMenuMigrationStep() {
val view = MigrationViewBuilder()
.text("1. Use the 'LAUNCH OLD APP' button below to launch the old app.")
.text("2. Tap on the 'three-lines' button at the top-left of the screen as shown below:")
.image(R.drawable.eh_migration_hamburgers)
.text("3. Highlight the 'Backup' item by tapping on it as shown below:")
.image(R.drawable.eh_migration_backup)
.text("4. Return to this app but <b>do not close</b> the old app.")
.text("5. When you have completed the above steps, tap 'CONTINUE'.")
.toView(context)
migrationStepDialog(1, null, MigrationStatus.PERFORM_BACKUP)
.customView(view, true)
.neutralText("Launch Old App")
.onNeutral { materialDialog, dialogAction ->
//Auto dismiss messes this up so we have to reopen the dialog manually
val ma = mainTachiyomiEHActivity()
if(ma != null) {
context.startActivity(ma)
} else {
context.toast("Failed to launch old app! Try launching it manually.")
}
openBackupMenuMigrationStep()
}
.show()
}
fun performBackupMigrationStep() {
val view = MigrationViewBuilder()
.text("6. Return to the old app.")
.text("7. Tap on the 'BACKUP' button in the old app (shown below):")
.image(R.drawable.eh_migration_backup_button)
.text("8. In the menu that appears, tap on 'Complete migration' (shown below):")
.image(R.drawable.eh_migration_share_icon)
.toView(context)
migrationStepDialog(2, MigrationStatus.OPEN_BACKUP_MENU, null)
.customView(view, true)
.show()
}
fun finalizeMigration() {
migrationDialog()
.title("Migration complete")
.content(fromHtmlCompat("Your library has been migrated over to the new app!<br><br>" +
"You may now uninstall the old app by pressing the 'UNINSTALL OLD APP' button below!<br><br>" +
"<b>If you were previously using ExHentai, your library may appear blank, just log in again to fix this.</b><br><br>" +
"Then tap 'OK' to exit the migration process!"))
.positiveText("Ok")
.neutralText("Uninstall Old App")
.onPositive { materialDialog, dialogAction ->
completeMigration()
//Check if the metadata needs to be updated
databaseHelper.getLibraryMangas().asRxSingle().subscribe {
if (it.size > 0)
context.runOnUiThread {
MetadataFetchDialog().tryAskMigration(context)
}
}
}
.onNeutral { materialDialog, dialogAction ->
val packageUri = Uri.parse("package:$TACHIYOMI_EH_PACKAGE")
val uninstallIntent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri)
context.startActivity(uninstallIntent)
//Cancel out auto-dismiss
finalizeMigration()
}
.show()
}
fun migrationDialog() = MaterialDialog.Builder(context)
.cancelable(false)
.canceledOnTouchOutside(false)
.showListener { dismissQueue?.add(it) }!!
fun migrationStepDialog(step: Int, previousStep: Int?, nextStep: Int?) = migrationDialog()
.title("Migration part $step of ${MigrationStatus.MAX_MIGRATION_STEPS}")
.apply {
if(previousStep != null) {
negativeText("Back")
onNegative { materialDialog, dialogAction -> jumpToMigrationStep(previousStep) }
}
if(nextStep != null) {
positiveText("Continue")
onPositive { materialDialog, dialogAction -> jumpToMigrationStep(nextStep) }
}
}!!
fun redDialog() = migrationDialog()
.backgroundColor(Color.parseColor("#F44336"))
.titleColor(Color.WHITE)
.contentColor(Color.WHITE)
.positiveColor(Color.WHITE)
.negativeColor(Color.WHITE)
.neutralColor(Color.WHITE)!!
fun completeMigration() {
preferenceHelper.migrationStatus().set(MigrationStatus.COMPLETED)
//Enable orientation changes again
context.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
}
fun jumpToMigrationStep(migrationStatus: Int) {
preferenceHelper.migrationStatus().set(migrationStatus)
//Too lazy to actually deal with orientation changes
context.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
when(migrationStatus) {
MigrationStatus.NOTIFY_USER -> notifyUserMigration()
MigrationStatus.OPEN_BACKUP_MENU -> openBackupMenuMigrationStep()
MigrationStatus.PERFORM_BACKUP -> performBackupMigrationStep()
MigrationStatus.FINALIZE_MIGRATION -> finalizeMigration()
}
}
companion object {
const val TACHIYOMI_EH_PACKAGE = "eu.kanade.tachiyomi.eh"
fun fromHtmlCompat(string: String)
= if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
Html.fromHtml(string, Html.FROM_HTML_MODE_LEGACY)
else
Html.fromHtml(string)
}
class MigrationViewBuilder {
val elements = mutableListOf<MigrationElement>()
fun text(text: String) = apply { elements += TextElement(text) }
fun image(drawable: Int) = apply { elements += ImageElement(drawable) }
fun toView(context: Activity): View {
val root = LinearLayout(context)
val rootParams = root.layoutParams ?: ViewGroup.LayoutParams(0, 0)
fun ViewGroup.LayoutParams.setup() = apply {
height = ViewGroup.LayoutParams.WRAP_CONTENT
width = ViewGroup.LayoutParams.MATCH_PARENT
}
fun dpToPx(dp: Float) = (dp * context.resources.displayMetrics.density + 0.5f).toInt()
rootParams.setup()
root.layoutParams = rootParams
root.gravity = Gravity.CENTER
root.orientation = LinearLayout.VERTICAL
for(element in elements) {
val view: View
if(element is TextElement) {
view = TextView(context)
view.text = fromHtmlCompat(element.value)
} else if(element is ImageElement) {
view = ImageView(context)
view.setImageResource(element.drawable)
view.adjustViewBounds = true
} else {
throw IllegalArgumentException("Unknown migration view!")
}
val viewParams = view.layoutParams ?: ViewGroup.LayoutParams(0, 0)
viewParams.setup()
view.layoutParams = viewParams
val eightDpAsPx = dpToPx(8f)
view.setPadding(0, eightDpAsPx, 0, eightDpAsPx)
root.addView(view)
}
return root
}
}
open class MigrationElement
class TextElement(val value: String): MigrationElement()
class ImageElement(val drawable: Int): MigrationElement()
}

View File

@ -1,4 +1,4 @@
package exh.ui
package exh.ui.migration
import android.app.Activity
import android.content.pm.ActivityInfo
@ -30,7 +30,7 @@ class MetadataFetchDialog {
context.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
val progressDialog = MaterialDialog.Builder(context)
.title("Migrating library")
.title("Fetching library metadata")
.content("Preparing library")
.progress(false, 0, true)
.cancelable(false)
@ -87,27 +87,40 @@ class MetadataFetchDialog {
}
fun askMigration(activity: Activity) {
MaterialDialog.Builder(activity)
.title("Migrate library")
.content("You need to migrate your library before tag searching in the library will function.\n\n" +
"This migration may take a long time depending on your library size and will also use up a significant amount of internet bandwidth.\n\n" +
"This process can be done later if required.")
.positiveText("Migrate")
.negativeText("Later")
.onPositive { materialDialog, dialogAction -> show(activity) }
.onNegative { materialDialog, dialogAction -> adviseMigrationLater(activity) }
.cancelable(false)
.canceledOnTouchOutside(false)
.dismissListener {
preferenceHelper.migrateLibraryAsked().set(true)
}.show()
var extra = ""
db.getLibraryMangas().asRxSingle().subscribe {
//Not logged in but have ExHentai galleries
if(!preferenceHelper.enableExhentai().getOrDefault()) {
it.find { it.source == 2 }?.let {
extra = "<b><font color='red'>If you use ExHentai, please log in first before fetching your library metadata!</font></b><br><br>"
}
}
activity.runOnUiThread {
MaterialDialog.Builder(activity)
.title("Fetch library metadata")
.content(LibraryMigrationManager.fromHtmlCompat("You need to fetch your library's metadata before tag searching in the library will function.<br><br>" +
"This process may take a long time depending on your library size and will also use up a significant amount of internet bandwidth.<br><br>" +
extra +
"This process can be done later if required."))
.positiveText("Migrate")
.negativeText("Later")
.onPositive { materialDialog, dialogAction -> show(activity) }
.onNegative { materialDialog, dialogAction -> adviseMigrationLater(activity) }
.cancelable(false)
.canceledOnTouchOutside(false)
.dismissListener {
preferenceHelper.migrateLibraryAsked().set(true)
}.show()
}
}
}
fun adviseMigrationLater(activity: Activity) {
MaterialDialog.Builder(activity)
.title("Migration canceled")
.content("Library migration has been canceled.\n\n" +
"You can run this operation later by going to: Settings > EHentai > Migrate Library")
.title("Metadata fetch canceled")
.content("Library metadata fetch has been canceled.\n\n" +
"You can run this operation later by going to: Settings > E-Hentai > Migrate library metadata")
.positiveText("Ok")
.cancelable(true)
.canceledOnTouchOutside(true)

View File

@ -0,0 +1,92 @@
package exh.ui.migration
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.ShareCompat
import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
import eu.kanade.tachiyomi.ui.main.MainActivity
import kotlinx.android.synthetic.main.toolbar.*
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import kotlin.concurrent.thread
/**
* Read backups directly from another Tachiyomi app
*/
class MigrationCompletionActivity : BaseActivity() {
private val backupManager by lazy { BackupManager(Injekt.get()) }
private val preferenceManager: PreferencesHelper by injectLazy()
override fun onCreate(savedInstanceState: Bundle?) {
setAppTheme()
super.onCreate(savedInstanceState)
setContentView(R.layout.eh_activity_finish_migration)
setup()
setupToolbar(toolbar, backNavigation = false)
supportActionBar?.setDisplayHomeAsUpEnabled(false)
}
fun setup() {
try {
val sc = ShareCompat.IntentReader.from(this)
Timber.i("CP: " + sc.callingPackage)
if(sc.isShareIntent) {
//Try to restore backup
thread {
//Finish old MainActivity
preferenceManager.finishMainActivity().set(true)
try {
backupManager.restoreFromStream(contentResolver.openInputStream(sc.stream))
} catch(t: Throwable) {
Timber.e(t, "Failed to restore manga/galleries!")
migrationError("Failed to restore manga/galleries!")
return@thread
}
//Go back to MainActivity
//Set final steps
preferenceManager.migrationStatus().set(MigrationStatus.FINALIZE_MIGRATION)
//Wait for MainActivity to finish
Thread.sleep(1000)
//Start new MainActivity
val intent = Intent(this, MainActivity::class.java)
intent.putExtra(MainActivity.Companion.FINALIZE_MIGRATION, true)
finish()
startActivity(intent)
}
}
} catch(t: Throwable) {
Timber.e(t, "Failed to migrate manga!")
migrationError("An unknown error occurred during migration!")
}
}
fun migrationError(message: String) {
runOnUiThread {
MaterialDialog.Builder(this)
.title("Migration error")
.content(message)
.positiveText("Ok")
.cancelable(false)
.canceledOnTouchOutside(false)
.dismissListener { finish() }
.show()
}
}
override fun onBackPressed() {
//Do not allow finishing this activity
}
}

View File

@ -0,0 +1,16 @@
package exh.ui.migration
class MigrationStatus {
companion object {
val NOT_INITIALIZED = -1
val COMPLETED = 0
//Migration process
val NOTIFY_USER = 1
val OPEN_BACKUP_MENU = 2
val PERFORM_BACKUP = 3
val FINALIZE_MIGRATION = 4
val MAX_MIGRATION_STEPS = 2
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/toolbar"/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_gravity="center">
<TextView
android:text="Finalizing migration..."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Medium.Title" />
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>

View File

@ -1,123 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<changelog bulletedList="true">
<changelogversion versionName="v0.4.1" changeDate="">
<changelogtext>Added an app's language selector.</changelogtext>
<changelogtext>Added options to sort the library and merged them with the filters.</changelogtext>
<changelogtext>Added an option to automatically download chapters.</changelogtext>
<changelogtext>Fixed performance issues when using a custom downloads directory, especially in the library updates tab.</changelogtext>
<changelogtext>Fixed gesture conflicts with the contextual menu and the webtoon reader.</changelogtext>
<changelogtext>Fixed wrong page direction when using volume keys for the right to left reader.</changelogtext>
<changelogtext>Fixed many crashes.</changelogtext>
</changelogversion>
<changelogversion versionName="v0.4.0" changeDate="">
<changelogtext>The download manager has been rewritten and it's possible some of your downloads
aren't recognized anymore. It's recommended to manually delete everything and start over.
</changelogtext>
<changelogtext>Now it's possible to download to any folder in a SD card.</changelogtext>
<changelogtext>The download directory setting has been reset.</changelogtext>
<changelogtext>Active downloads now persist after restarts.</changelogtext>
<changelogtext>Allow to bookmark chapters.</changelogtext>
<changelogtext>Allow to share or save a single page while reading with a long tap.</changelogtext>
<changelogtext>Added italian translation.</changelogtext>
<changelogtext>Image is now the default decoder.</changelogtext>
</changelogversion>
<changelogversion versionName="v0.3.2" changeDate="">
<changelogtext>Added a new image decoder. It should be faster than Rapid and more reliable than Skia.</changelogtext>
<changelogtext>Removed the advanced setting reencode images. Use the new image decoder instead.</changelogtext>
</changelogversion>
<changelogversion versionName="v0.3.1" changeDate="">
<changelogtext>Fixed a crash when opening latest updates. ([a href="https://github.com/inorichi/tachiyomi/issues/495"]#495[/a])</changelogtext>
</changelogversion>
<changelogversion versionName="v0.3.0" changeDate="">
<changelogtext>Added a new tab to show latest manga updates from the catalogues. ([a href="https://github.com/inorichi/tachiyomi/issues/61"]#61[/a])</changelogtext>
<changelogtext>Added genre filter for catalogues. ([a href="https://github.com/inorichi/tachiyomi/issues/428"]#428[/a])</changelogtext>
<changelogtext>Added an optional auto updater (not available for F-Droid installs). ([a href="https://github.com/inorichi/tachiyomi/issues/449"]#449[/a])</changelogtext>
<changelogtext>Added an option to display the library as a list. ([a href="https://github.com/inorichi/tachiyomi/issues/224"]#224[/a])</changelogtext>
<changelogtext>Added a customizable color filter for the reader. ([a href="https://github.com/inorichi/tachiyomi/issues/432"]#432[/a])</changelogtext>
<changelogtext>Added share intent in the info tab of a manga. ([a href="https://github.com/inorichi/tachiyomi/issues/340"]#340[/a])</changelogtext>
<changelogtext>Allow to launcher shortcuts for manga. ([a href="https://github.com/inorichi/tachiyomi/issues/435"]#435[/a])</changelogtext>
<changelogtext>Allow to select categories to update in global update. ([a href="https://github.com/inorichi/tachiyomi/issues/461"]#461[/a])</changelogtext>
<changelogtext>Redesigned source tab in preferences, now it allows to hide unwanted sources and languages. ([a href="https://github.com/inorichi/tachiyomi/issues/447"]#447[/a])</changelogtext>
<changelogtext>Fixed single page chapters not appending the next one. ([a href="https://github.com/inorichi/tachiyomi/issues/468"]#468[/a])</changelogtext>
<changelogtext>Fixed reader status bar reappearing after focus restore. ([a href="https://github.com/inorichi/tachiyomi/issues/408"]#408[/a])</changelogtext>
<changelogtext>Fixed various crashes in the webtoon reader.</changelogtext>
</changelogversion>
<changelogversion versionName="v0.2.3" changeDate="">
<changelogtext>Added a history of reading. ([a href="https://github.com/inorichi/tachiyomi/issues/316"]#316[/a])</changelogtext>
<changelogtext>Added an option to select the initial screen. ([a href="https://github.com/inorichi/tachiyomi/issues/395"]#395[/a])</changelogtext>
<changelogtext>Added spanish and portuguese translations. ([a href="https://github.com/inorichi/tachiyomi/issues/365"]#365[/a], [a href="https://github.com/inorichi/tachiyomi/issues/375"]#375[/a])</changelogtext>
<changelogtext>Added sources "Mangasee" and "Wie Manga!" ([a href="https://github.com/inorichi/tachiyomi/issues/355"]#355[/a], [a href="https://github.com/inorichi/tachiyomi/issues/379"]#379[/a])</changelogtext>
<changelogtext>New design for the reader's menu. ([a href="https://github.com/inorichi/tachiyomi/issues/368"]#368[/a])</changelogtext>
<changelogtext>When resuming chapters, the new loader starts from the page that was opened, instead of from the beginning. ([a href="https://github.com/inorichi/tachiyomi/issues/268"]#268[/a])</changelogtext>
<changelogtext>Custom brightness in the reader can be set even lower by applying a black layer on the top. ([a href="https://github.com/inorichi/tachiyomi/issues/362"]#362[/a])</changelogtext>
<changelogtext>Fixed reader's status bar reappearing in Android versions older than Kit Kat. ([a href="https://github.com/inorichi/tachiyomi/issues/359"]#359[/a])</changelogtext>
<changelogtext>Fixed UI bugs. ([a href="https://github.com/inorichi/tachiyomi/issues/332"]#332[/a], [a href="https://github.com/inorichi/tachiyomi/issues/333"]#333[/a], [a href="https://github.com/inorichi/tachiyomi/issues/351"]#351[/a], [a href="https://github.com/inorichi/tachiyomi/issues/361"]#361[/a])</changelogtext>
<changelogtext>Fixed empty library covers.</changelogtext>
<changelogtext>Fixed some random crashes (most of them when downloading chapters).</changelogtext>
</changelogversion>
<changelogversion versionName="v0.2.2" changeDate="">
<changelogtext>[b]Important![/b] Now chapters follow the order of the sources. [b]It's required that you update your entire library
before reading to sync them.[/b] Old behavior can be restored for a manga in the overflow menu of the chapters tab.
<changelogtext>[b]Important![/b] The application is now signed with a different key, you must migrate over your previous library if you wish to keep it!
</changelogtext>
<changelogtext>Kissmanga now loads through CloudFlare.</changelogtext>
<changelogtext>Persistent cookies have been added for a better experience with CloudFlare sites.</changelogtext>
<changelogtext>Added link to manga website in the info page. [a href="https://github.com/inorichi/tachiyomi/issues/157"]#157[/a]</changelogtext>
<changelogtext>Added notifications for downloads. [a href="https://github.com/inorichi/tachiyomi/pull/289"]#289[/a]</changelogtext>
<changelogtext>Added more options to recent updates. [a href="https://github.com/inorichi/tachiyomi/pull/324"]#324[/a]</changelogtext>
<changelogtext>Remember last active category. [a href="https://github.com/inorichi/tachiyomi/issues/261"]#261[/a]</changelogtext>
<changelogtext>Fixed a bug with seamless mode for chapters with less than 5 pages. [a href="https://github.com/inorichi/tachiyomi/issues/291"]#291[/a]</changelogtext>
<changelogtext>Improved chapter recognition.</changelogtext>
<changelogtext>Bugfixes and more improvements.</changelogtext>
</changelogversion>

View File

@ -25,8 +25,8 @@
<SwitchPreference
android:title="Show Japanese titles in search results"
android:summaryOn="Currently showing Japanese titles in search results"
android:summaryOff="Currently showing English/Romanized titles in search results"
android:summaryOn="Currently showing Japanese titles in search results. Clear the chapter cache after changing this (in the Advanced section)"
android:summaryOff="Currently showing English/Romanized titles in search results. Clear the chapter cache after changing this (in the Advanced section)"
android:key="use_jp_title"
android:defaultValue="false" />
@ -46,7 +46,7 @@
android:entryValues="@array/ehentai_quality_values" />
<ListPreference
android:title="Search result count"
android:title="Search result count per page"
android:summary="Requires the \'Paging Enlargement\' hath perk"
android:defaultValue="rc_0"
android:key="ex_search_size"
@ -57,7 +57,7 @@
<ListPreference
android:defaultValue="tr_2"
android:title="Thumbnail rows"
android:summary="It is recommended to set this to the maximum size your hath perks allow"
android:summary="Affects loading speeds. It is recommended to set this to the maximum size your hath perks allow"
android:key="ex_thumb_rows"
android:dependency="enable_exhentai"
android:entries="@array/ehentai_thumbnail_rows"
@ -67,10 +67,10 @@
android:title="Advanced"
android:persistent="false">
<Preference
android:title="Migrate library"
android:title="Migrate library metadata"
android:persistent="false"
android:key="ex_migrate_library"
android:summary="Migrate your library to enable tag searching in the library. This button will be visible even if you have already migrated your library" />
android:summary="Fetch the library metadata to enable tag searching in the library. This button will be visible even if you have already fetched the metadata" />
</PreferenceCategory>
</PreferenceScreen>