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 000000000..9d58af1e3 Binary files /dev/null and b/app/src/main/res/drawable/eh_migration_backup.png differ 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 000000000..9903385c9 Binary files /dev/null and b/app/src/main/res/drawable/eh_migration_backup_button.png differ 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 000000000..8e491b1e5 Binary files /dev/null and b/app/src/main/res/drawable/eh_migration_hamburgers.png differ 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 000000000..7749f7797 Binary files /dev/null and b/app/src/main/res/drawable/eh_migration_share_icon.png differ 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" />