From 2b988c51ad93c4fb844c2a5ff817bf9604eeb121 Mon Sep 17 00:00:00 2001 From: NerdNumber9 Date: Fri, 6 Jan 2017 18:01:40 -0500 Subject: [PATCH] Add migration system. --- app/src/main/AndroidManifest.xml | 9 + .../data/preference/PreferencesHelper.kt | 5 + .../ui/library/LibraryCategoryView.kt | 2 +- .../ui/main/ChangelogDialogFragment.kt | 2 +- .../kanade/tachiyomi/ui/main/MainActivity.kt | 32 ++- .../ui/setting/SettingsEhFragment.kt | 2 +- .../ui/migration/LibraryMigrationManager.kt | 263 ++++++++++++++++++ .../ui/{ => migration}/MetadataFetchDialog.kt | 51 ++-- .../migration/MigrationCompletionActivity.kt | 92 ++++++ .../java/exh/ui/migration/MigrationStatus.kt | 16 ++ .../main/res/drawable/eh_migration_backup.png | Bin 0 -> 30201 bytes .../drawable/eh_migration_backup_button.png | Bin 0 -> 4700 bytes .../res/drawable/eh_migration_hamburgers.png | Bin 0 -> 6818 bytes .../res/drawable/eh_migration_share_icon.png | Bin 0 -> 9088 bytes .../layout/eh_activity_finish_migration.xml | 48 ++++ app/src/main/res/raw/changelog_release.xml | 116 +------- app/src/main/res/xml/eh_pref_eh.xml | 12 +- 17 files changed, 498 insertions(+), 152 deletions(-) create mode 100644 app/src/main/java/exh/ui/migration/LibraryMigrationManager.kt rename app/src/main/java/exh/ui/{ => migration}/MetadataFetchDialog.kt (66%) create mode 100644 app/src/main/java/exh/ui/migration/MigrationCompletionActivity.kt create mode 100644 app/src/main/java/exh/ui/migration/MigrationStatus.kt create mode 100644 app/src/main/res/drawable/eh_migration_backup.png create mode 100644 app/src/main/res/drawable/eh_migration_backup_button.png create mode 100644 app/src/main/res/drawable/eh_migration_hamburgers.png create mode 100644 app/src/main/res/drawable/eh_migration_share_icon.png create mode 100644 app/src/main/res/layout/eh_activity_finish_migration.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 72faea00a..0ed841bbf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -132,6 +132,15 @@ android:scheme="https"/> + + + + + + + diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index fab0ba15b..62804132d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -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 Preference.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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt index 9cb52bd6e..ae7e7d62c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt @@ -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() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt index db7eee11b..e6de71544 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt @@ -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 } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index b7172f494..f80333ae6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -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() + 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().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" } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhFragment.kt index 23d18e5cb..37865619d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhFragment.kt @@ -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 diff --git a/app/src/main/java/exh/ui/migration/LibraryMigrationManager.kt b/app/src/main/java/exh/ui/migration/LibraryMigrationManager.kt new file mode 100644 index 000000000..ac45ace95 --- /dev/null +++ b/app/src/main/java/exh/ui/migration/LibraryMigrationManager.kt @@ -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? = 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 do not close 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!

" + + "You may now uninstall the old app by pressing the 'UNINSTALL OLD APP' button below!

" + + "If you were previously using ExHentai, your library may appear blank, just log in again to fix this.

" + + "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() + 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() +} + diff --git a/app/src/main/java/exh/ui/MetadataFetchDialog.kt b/app/src/main/java/exh/ui/migration/MetadataFetchDialog.kt similarity index 66% rename from app/src/main/java/exh/ui/MetadataFetchDialog.kt rename to app/src/main/java/exh/ui/migration/MetadataFetchDialog.kt index edbc405d5..922bd25be 100644 --- a/app/src/main/java/exh/ui/MetadataFetchDialog.kt +++ b/app/src/main/java/exh/ui/migration/MetadataFetchDialog.kt @@ -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 = "If you use ExHentai, please log in first before fetching your library metadata!

" + } + } + 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.

" + + "This process may take a long time depending on your library size and will also use up a significant amount of internet bandwidth.

" + + 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) diff --git a/app/src/main/java/exh/ui/migration/MigrationCompletionActivity.kt b/app/src/main/java/exh/ui/migration/MigrationCompletionActivity.kt new file mode 100644 index 000000000..f2571835a --- /dev/null +++ b/app/src/main/java/exh/ui/migration/MigrationCompletionActivity.kt @@ -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 + } +} + diff --git a/app/src/main/java/exh/ui/migration/MigrationStatus.kt b/app/src/main/java/exh/ui/migration/MigrationStatus.kt new file mode 100644 index 000000000..1fa3aa5cf --- /dev/null +++ b/app/src/main/java/exh/ui/migration/MigrationStatus.kt @@ -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 + } +} diff --git a/app/src/main/res/drawable/eh_migration_backup.png b/app/src/main/res/drawable/eh_migration_backup.png new file mode 100644 index 0000000000000000000000000000000000000000..9d58af1e3e61fbc73e3f1aa1a7f266f476e7e016 GIT binary patch literal 30201 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 VQb4AF{_hU1;Fl1^a`|_`{{y2xGmZcN literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/eh_migration_backup_button.png b/app/src/main/res/drawable/eh_migration_backup_button.png new file mode 100644 index 0000000000000000000000000000000000000000..9903385c9f8dd2d229f5ff841d8c38e65052a834 GIT binary patch literal 4700 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 X{UY^2rI#kKGX#R@!E{URJbLyYvRMg7 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/eh_migration_hamburgers.png b/app/src/main/res/drawable/eh_migration_hamburgers.png new file mode 100644 index 0000000000000000000000000000000000000000..8e491b1e5ce416da680a17e0f0f907bbb08414b8 GIT binary patch literal 6818 zcmb7}byQT*+wTV$Vd$Z|k(Lr^ff>5HrH2v_kdTrbQW^!MLqSqX8l*#Mq(d5{yW>6l z*1O)j?!D{&ao4Pwb7tq+&))kv&-b$3GfVW!h^P>nHa<1TrHHLKDC?L=oMNHobu{?O|Q68C|Y~jn%^1uCxDCY{&L> zrrh`}uc^Et{e*PtvVE&_gIBq3dTf%L7Bl|SUmLq zkS0lUIHDXOX`}pc ziH&gK9xovj+aZqbE{0QY4POQR&LHRzVQMa59f+OsQ6AYNi{Q5B)!`S>L3z9NvTKbv z7-?QM!z&n!EGO+cgKNBf3d@jf;(ssQ%YO$?XD|p zD#t@h(KX-GDCkZw87@Tdn$)TObqIuogF^7c(z#JUf5xDH!k*?BB|xmr!Lq!S9Ks^M z1lJ<&)et{SI!Ubus|v4c!zPV`IW^h8MX1TkO9{(9hr!!A-rEp*tEME3YoUbJI&@E^ zuOE%_oQF@!2g7(IaeSk4FAjUY^b%a#bXWAe8GEk*l{Ubh zE0LOxn%SD|kjgQ?nxy=5YETQ|vGhoc1JhPbKYrS z!A?y5jT8xexDtzeiU9e7f6&O4!ql4oS9BV9*fq3xCkS2wR6zTy*jZKn1H}4DWjbu7 zOZ*#Z2U`bbFH!K9A@tqyhCpJE{E2LuW8!>1fpbsGH&R@_Ie)v&zPDtyscgLt`dh!a z?eGWrbjeXkV!J~~`wP)I5174JRNQrsdc|k9^!nAD+>>IG$ZxpHfpVm;$Ny@U@4>4Y z35tq+WX$vp&t^83?EDg1v0p?nM|pMJBk5~5eRoU5W0+N|yR+>t@TFzlMayNrmd@w| zlqFEQPv@1w^yXg3;C*{`|0+`)FWY(_rhLc})i%_l%=V23))m;Zd-+6onMXu@xq9H`DJT789JI@$Zlybs zk*#JUr1{(?v2+ragyosWBvm0V{6A>%V-O=DX;gsg2=nbj*t~U!ezQ#>O+1WSGu{c{_y;adZWV!8KG|S<7 z!@0C3lO<3BRxM;V&0{)tVGX;!b* z6U}9}FUy7DtfrGnajb_~M|^j0FkifyFNQ+u!FMA z+>6JWE<$Q_*0GUkSWM9 zF&I!CQ?+*HK9{fjqkX>|{(#3?eUVr<8DS*LcuKpdpgmDNjt#1sE9PBc51Z||KtOji zAfEbUtDjczg>O7esSYQ#e|AiK(>eY_IsT7F-pUSVrO9|%;&;~PuSMIu4DRy1avZ^M zc!iR<(R*4Rv)k0_pHJDa9jyrc@dfndset=!umU8>t8nCYDgf8fTsO zb_IxDPv;M^qiSqA*K>WDughhH0ipK#zx4h(7nm$)P-e&Ebtrf_3PA1xej}F+FVW)E3g!k4cg~wk#$Q>=L_DUX+PDa;-4(6qm(!2Iay- z#8k@`&EI>2&GzB*M?Y%+HIR3=obYWQN`_+p=I+D#=X`~2M|$Z5sDWBUIfk>JcWU*6 zyAn$5=1(cwNmEJPvss1h?h%Ha&lOS%fO8tII_G6C?-whnY z_h@#;3c*Z>`X-BAGL*}jr24xc7s|n&cW85knwRr1C*VZP&#l=@4ppw$`3W(D*cCHz zFaKG4y0|L_AD*v%PsEs{aF)F1XcV6GygfZ;SE5aX-U{>Z4jQVPryWGSqkI2EyGG4? zfp49oqbaU6*uIss`oa7N6OuCh94?#+rLI5Zvz5)bc=t234M?S~?yBSVD4Sv}z;m6rRJ8^Kfz#FP1&~ zVxKSHw)>=F8NuqN7TGeVqvwT1hhNcn*Y?8WY9*a?9ig5qV2WR_yH0Ul!d3ipDQScL53{yE5pRi)t|4&W7q*W%SJY&V!y6(Q~GZsp_*yD|_$fx(D9-LxA0 zaMm$J5j+JC8N%XDBGp+d-%ko70!cx;x)9o89_!ldUtY-4og9~|EKa=$4{k7jOKd}T zJ%a#gS^Fr$1mo)qVM^TGN|rstUmSg>qWtkKm@wL2|KO9z281C-I463&Wtc%PJbv8B zeoSzQDOXh%%#lCN*JhyjD~iIB1{;>w7}+pb&+JcS_-QE`@S0G<2~`BOFF~+M?6H+K z-)DrbWxv5v6pbYf7R<-DOwl+~JXVmDpl-~u3^{&oPNq9z2=8A4(oRU<&G!@)BOibK zjIFL9{53g()~WnBWv&J`CGEMeXwe-3I0~&!`e$(C;L}U!?N!Ny2$zkm5A!_o_R}y# zF!r=M8|CXqI{JY%OkqnTXF&vA{FM(QlZ3l&`KKSBZ}4k%;n22e_y(1iQ_20b1F^MiRe7H0wV zr&!b4XM*xh$igNU*{Px7h~T88B*mK*#*rB@$4n>?fu+}+efYWt>tHmf?1*BQ|JoRu zDNcfQ*{2@&YV^mr<#e3QcB_So%AgS|SR$!_vmL!p z&dLk?E_8Er_qK)7ul0imd`aY`#hBnOI}1J`X?qljo{9(uDlPttvX=v`6>Yc?IEIUJ zpPUqTr*6idyVZNCVxnZ*W~X>FhCRk$KZO9OUc{yRu|n!idE{~ zlh$>`PA^#y{B}m9`BzW5n5APGpgt;VmD1a!m=P{%ipxU?_8SSW~BcN zTH$p1O%_Zw#C;kq&qbwIT4DK1li=_`yvR-U!JB)CZQ9bGDG?alnksCdwdZ_?oL^;; z0M)^aZm1#kjX_Q+j|F?FfkpSn{9y|OkiQ(rx|^t{Kn0{ zeq@}XfoIY32SJ$17Ts9usrzXJw`@%TUo|_a$=J?dmO4v`Q@=LYUh{v;mhx`79^xAO zgl}uhy0b{Bf+c&HDKI}?ORE<)Du|d1B;njyE*lT=5 Ra4Lz{zN8iJ;p}X#f&AgT z5e{WE8Zx~O_))Zz72vxt-)TM(9e75YIvGWj+z~}$6#ljjIxogF5*wYb*u7YgNlgP5 z(m%J-ZBJ&a7f!#gapvM$>X`7|k%^iIPhz7uSd;J3GI52HaMtjDGKPSbw4ODU=QpJX zo|H-XP>Y3+6pZG|`yNE!C#M=b1(*IF;DB=ai* zKXhO!Nu)KJfukcGQ>g?Q_`^4vV*vX2ShFoY7!ui;RZX+=-Hvfs3G@O>rVQ&Gmi)l9 zjioC`9S{Vs4?qlV`mOV&p@UwB^2JI&U*C_9tn|XiXtQr3SbMpmo(5BuZ_AeZ(Y{TbscqH`wVMbH z+{us@J;+)L<`mo-P}wmk_8}rrQw1?7Gr9KrSvo0u=Wr= z5+h~VklB^W_o8T<{zwvRls1V2iQFa{6{+!lH+TR7iQKAwuGf1Q=z+@o!RCjOMa>M*jLF^8BYYEn9+5oWPj1X0d#)$s-1mTcncZ@ERMq2F0fy$6@<2W_1GP9#s8ZXmY1+3xu}} zUQ+_UvBWINgNB&^1$I0K!8V*5- z7;!MAEMYNmB+Fhf)ycG(kxX)}+j$Bp%*AT)ON&xM1dvP7r-=lCqN=jZYn`2%!f0Zw z5l&*(@>UeJZ@Cy(qcA&SLvzL@am>C-4D5;l5%6q0A{>~&$6(mzuYM7J{tF8OeX`r<$eXoCODO;{idVf(fc#PB*gj;X zSpu4c!Mm#mm=WpSBKD2lfSV)z(LrIwchr7x|ncmUy?fdvLDbfEoN-o&*}Em<#FOX0Zu4JoM=D2#7=X<|;7x zmw9^E_0A9M?0?Ozl`On)eL1vw=%Iu{@d0VR4k%x9_}0*ss1mAq>v%>Z&0qYRCXXdh=Nr@6Wh~sU9-p3Z$MnH>2I}=2 zJ1D^3WBR*o|6G<38x+|Hc-Mk-PJ9<%2`Fp2A6&#Q{izaW^l;0grP7LN0dM%tT1Sde zZ)kWZAkda4du7)wkm&v-5&$3E>Cv+A3eVH)CwU?WB0&cu03-1B%HY_=7Z-=i5h4lH z&5q|epspsNfBnyC`E};4H^X0cUDg%ijgDCm2H$kX*UJ&+)E8rNy6?M5A-y~jm@`!;Jif4N${sJb@wW% zNw?AkwBV5jMD*PcJ?*t`xzqUALiY8@xIZ7~Z8~>;#Vs+yW+=rDAJRJ-O!jSw4Kv8; z7;aCH)$B95TfdQG=a<}oab|I}W(bPhW_g5Z^`+PR3W`Jge)$i*y8)$Wj zYwh#`9QBbGzNQfv&zzqLTzEkyOy;lv+7ny5@hS`4o2*t#W&)G99?rX(v z*V)ttI=hih2JUZbo#nZ?&23ko68}k|w`^-R;BLbV==a6~U|_BpO65Hgbh)e%^M9j2 z>vx>Qofrar_C->ra6aA})h8wgsVCTF()?InXn}j?--%brN zlot*b5C3q|0bp?ip#SX$BXle!0cP3E) z$F%GaBxc=!kx1>JKrl#yjR7&i`28RMTO*F-S5=Pe)#4J@-S>dw;N4me2M9gD$N=sEZV z`{9o$Hu177mAFwGLBtH^V!RehnDE3k{`ew3X14ce*T@+Y*fu$gqBJxp%fy2K%YGqq z=0UHk8wX&r4)=wf?Zt`zoxsE36_k$TR4};y@4c>9fiPR`i>U)9fJ-~##B^7XO<2+^ zKqjgGk3)ne=Qu*3E5I)drgnMS$)= zz#tTQ!YY6f9d)ra7xpXxqa588n2&xA9iVE@&JI6WK?Rw&_fxou(?*M<6g+`HQhdNf znh9i&_BtoF8u^WHM287jlK1$@8YmdqrpI^u1laK!Uuiqu{C}Lc{LhKZeD?#Ix5shk URzX`TaGC^ClvR@{hnolg7yOpF!vFvP literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/eh_migration_share_icon.png b/app/src/main/res/drawable/eh_migration_share_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7749f77976546670fee0f5c37648c972972cad29 GIT binary patch literal 9088 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/eh_activity_finish_migration.xml b/app/src/main/res/layout/eh_activity_finish_migration.xml new file mode 100644 index 000000000..e96f46e38 --- /dev/null +++ b/app/src/main/res/layout/eh_activity_finish_migration.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/raw/changelog_release.xml b/app/src/main/res/raw/changelog_release.xml index 45567a143..71969b1f5 100644 --- a/app/src/main/res/raw/changelog_release.xml +++ b/app/src/main/res/raw/changelog_release.xml @@ -1,123 +1,9 @@ - - - Added an app's language selector. - - Added options to sort the library and merged them with the filters. - - Added an option to automatically download chapters. - - Fixed performance issues when using a custom downloads directory, especially in the library updates tab. - - Fixed gesture conflicts with the contextual menu and the webtoon reader. - - Fixed wrong page direction when using volume keys for the right to left reader. - - Fixed many crashes. - - - - 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. - - - Now it's possible to download to any folder in a SD card. - - The download directory setting has been reset. - - Active downloads now persist after restarts. - - Allow to bookmark chapters. - - Allow to share or save a single page while reading with a long tap. - - Added italian translation. - - Image is now the default decoder. - - - - Added a new image decoder. It should be faster than Rapid and more reliable than Skia. - - Removed the advanced setting reencode images. Use the new image decoder instead. - - - - Fixed a crash when opening latest updates. ([a href="https://github.com/inorichi/tachiyomi/issues/495"]#495[/a]) - - - - Added a new tab to show latest manga updates from the catalogues. ([a href="https://github.com/inorichi/tachiyomi/issues/61"]#61[/a]) - - Added genre filter for catalogues. ([a href="https://github.com/inorichi/tachiyomi/issues/428"]#428[/a]) - - Added an optional auto updater (not available for F-Droid installs). ([a href="https://github.com/inorichi/tachiyomi/issues/449"]#449[/a]) - - Added an option to display the library as a list. ([a href="https://github.com/inorichi/tachiyomi/issues/224"]#224[/a]) - - Added a customizable color filter for the reader. ([a href="https://github.com/inorichi/tachiyomi/issues/432"]#432[/a]) - - Added share intent in the info tab of a manga. ([a href="https://github.com/inorichi/tachiyomi/issues/340"]#340[/a]) - - Allow to launcher shortcuts for manga. ([a href="https://github.com/inorichi/tachiyomi/issues/435"]#435[/a]) - - Allow to select categories to update in global update. ([a href="https://github.com/inorichi/tachiyomi/issues/461"]#461[/a]) - - 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]) - - Fixed single page chapters not appending the next one. ([a href="https://github.com/inorichi/tachiyomi/issues/468"]#468[/a]) - - Fixed reader status bar reappearing after focus restore. ([a href="https://github.com/inorichi/tachiyomi/issues/408"]#408[/a]) - - Fixed various crashes in the webtoon reader. - - - - Added a history of reading. ([a href="https://github.com/inorichi/tachiyomi/issues/316"]#316[/a]) - - Added an option to select the initial screen. ([a href="https://github.com/inorichi/tachiyomi/issues/395"]#395[/a]) - - 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]) - - 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]) - - New design for the reader's menu. ([a href="https://github.com/inorichi/tachiyomi/issues/368"]#368[/a]) - - 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]) - - 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]) - - Fixed reader's status bar reappearing in Android versions older than Kit Kat. ([a href="https://github.com/inorichi/tachiyomi/issues/359"]#359[/a]) - - 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]) - - Fixed empty library covers. - - Fixed some random crashes (most of them when downloading chapters). - - - [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. + [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! - Kissmanga now loads through CloudFlare. - - Persistent cookies have been added for a better experience with CloudFlare sites. - - Added link to manga website in the info page. [a href="https://github.com/inorichi/tachiyomi/issues/157"]#157[/a] - - Added notifications for downloads. [a href="https://github.com/inorichi/tachiyomi/pull/289"]#289[/a] - - Added more options to recent updates. [a href="https://github.com/inorichi/tachiyomi/pull/324"]#324[/a] - - Remember last active category. [a href="https://github.com/inorichi/tachiyomi/issues/261"]#261[/a] - - Fixed a bug with seamless mode for chapters with less than 5 pages. [a href="https://github.com/inorichi/tachiyomi/issues/291"]#291[/a] - - Improved chapter recognition. - Bugfixes and more improvements. diff --git a/app/src/main/res/xml/eh_pref_eh.xml b/app/src/main/res/xml/eh_pref_eh.xml index 3c99fe488..5ec63237a 100644 --- a/app/src/main/res/xml/eh_pref_eh.xml +++ b/app/src/main/res/xml/eh_pref_eh.xml @@ -25,8 +25,8 @@ @@ -46,7 +46,7 @@ android:entryValues="@array/ehentai_quality_values" /> + 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" />