mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Add migration system.
This commit is contained in:
		@@ -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>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										263
									
								
								app/src/main/java/exh/ui/migration/LibraryMigrationManager.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								app/src/main/java/exh/ui/migration/LibraryMigrationManager.kt
									
									
									
									
									
										Normal 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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								app/src/main/java/exh/ui/migration/MigrationStatus.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/src/main/java/exh/ui/migration/MigrationStatus.kt
									
									
									
									
									
										Normal 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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_backup.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_backup.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 30 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_backup_button.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_backup_button.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.6 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_hamburgers.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_hamburgers.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 6.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_share_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable/eh_migration_share_icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 8.9 KiB  | 
							
								
								
									
										48
									
								
								app/src/main/res/layout/eh_activity_finish_migration.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/src/main/res/layout/eh_activity_finish_migration.xml
									
									
									
									
									
										Normal 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>
 | 
			
		||||
@@ -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>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user