From ae5ad2a9a6fa3a4f2139712564a0b561ed00b37a Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 7 Nov 2019 00:43:25 -0800 Subject: [PATCH] Added Select all and source migration to selected manga on library screen --- .../ui/library/LibraryCategoryView.kt | 10 +++ .../tachiyomi/ui/library/LibraryController.kt | 63 ++++++++++++-- .../tachiyomi/ui/library/LibraryPresenter.kt | 77 ++++++++++++++++++ .../ui/migration/MigrationController.kt | 26 ++++-- .../ui/migration/SearchController.kt | 34 ++++++-- .../baseline_swap_calls_white_18.png | Bin 0 -> 248 bytes .../baseline_swap_calls_white_24.png | Bin 0 -> 291 bytes .../baseline_swap_calls_white_36.png | Bin 0 -> 426 bytes .../baseline_swap_calls_white_48.png | Bin 0 -> 443 bytes .../baseline_swap_calls_white_18.png | Bin 0 -> 204 bytes .../baseline_swap_calls_white_24.png | Bin 0 -> 186 bytes .../baseline_swap_calls_white_36.png | Bin 0 -> 291 bytes .../baseline_swap_calls_white_48.png | Bin 0 -> 323 bytes .../baseline_swap_calls_white_18.png | Bin 0 -> 291 bytes .../baseline_swap_calls_white_24.png | Bin 0 -> 323 bytes .../baseline_swap_calls_white_36.png | Bin 0 -> 443 bytes .../baseline_swap_calls_white_48.png | Bin 0 -> 580 bytes .../baseline_swap_calls_white_18.png | Bin 0 -> 426 bytes .../baseline_swap_calls_white_24.png | Bin 0 -> 443 bytes .../baseline_swap_calls_white_36.png | Bin 0 -> 740 bytes .../baseline_swap_calls_white_48.png | Bin 0 -> 872 bytes .../baseline_swap_calls_white_18.png | Bin 0 -> 443 bytes .../baseline_swap_calls_white_24.png | Bin 0 -> 580 bytes .../baseline_swap_calls_white_36.png | Bin 0 -> 872 bytes .../baseline_swap_calls_white_48.png | Bin 0 -> 1270 bytes .../res/drawable/baseline_swap_calls_24.xml | 10 +++ app/src/main/res/menu/library_selection.xml | 11 +++ 27 files changed, 208 insertions(+), 23 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/baseline_swap_calls_white_18.png create mode 100644 app/src/main/res/drawable-hdpi/baseline_swap_calls_white_24.png create mode 100644 app/src/main/res/drawable-hdpi/baseline_swap_calls_white_36.png create mode 100644 app/src/main/res/drawable-hdpi/baseline_swap_calls_white_48.png create mode 100644 app/src/main/res/drawable-mdpi/baseline_swap_calls_white_18.png create mode 100644 app/src/main/res/drawable-mdpi/baseline_swap_calls_white_24.png create mode 100644 app/src/main/res/drawable-mdpi/baseline_swap_calls_white_36.png create mode 100644 app/src/main/res/drawable-mdpi/baseline_swap_calls_white_48.png create mode 100644 app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_18.png create mode 100644 app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_24.png create mode 100644 app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_36.png create mode 100644 app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_48.png create mode 100644 app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_18.png create mode 100644 app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_24.png create mode 100644 app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_36.png create mode 100644 app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_48.png create mode 100644 app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_18.png create mode 100644 app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_24.png create mode 100644 app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_36.png create mode 100644 app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_48.png create mode 100644 app/src/main/res/drawable/baseline_swap_calls_24.xml 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 e1edb981f6..b64c25dbf7 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 @@ -126,6 +126,16 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att subscriptions += controller.selectionRelay .subscribe { onSelectionChanged(it) } + + subscriptions += controller.selectAllRelay + .subscribe { + if (it == category.id) { + adapter.currentItems.forEach { item -> + controller.setSelection(item.manga, true) + } + controller.invalidateActionMode() + } + } } fun onRecycle() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 3f3e088737..ca2d3eebb0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -5,20 +5,24 @@ import android.content.Intent import android.content.res.Configuration import android.graphics.Color import android.net.Uri -import android.os.Build import android.os.Bundle -import com.google.android.material.tabs.TabLayout -import androidx.core.graphics.drawable.DrawableCompat +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.view.WindowInsets import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.SearchView -import android.view.* -import androidx.appcompat.widget.ActionBarContextView +import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.GravityCompat import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeType import com.f2prateek.rx.preferences.Preference import com.google.android.material.snackbar.Snackbar +import com.google.android.material.tabs.TabLayout import com.jakewharton.rxbinding.support.v4.view.pageSelections import com.jakewharton.rxbinding.support.v7.widget.queryTextChanges import com.jakewharton.rxrelay.BehaviorRelay @@ -37,7 +41,15 @@ import eu.kanade.tachiyomi.ui.category.CategoryController import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.migration.MigrationController -import eu.kanade.tachiyomi.util.* +import eu.kanade.tachiyomi.ui.migration.MigrationInterface +import eu.kanade.tachiyomi.ui.migration.SearchController +import eu.kanade.tachiyomi.util.doOnApplyWindowInsets +import eu.kanade.tachiyomi.util.inflate +import eu.kanade.tachiyomi.util.marginBottom +import eu.kanade.tachiyomi.util.marginTop +import eu.kanade.tachiyomi.util.snack +import eu.kanade.tachiyomi.util.toast +import eu.kanade.tachiyomi.util.updatePaddingRelative import kotlinx.android.synthetic.main.library_controller.* import kotlinx.android.synthetic.main.main_activity.* import rx.Subscription @@ -46,7 +58,6 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.IOException - class LibraryController( bundle: Bundle? = null, private val preferences: PreferencesHelper = Injekt.get() @@ -55,7 +66,8 @@ class LibraryController( SecondaryDrawerController, ActionMode.Callback, ChangeMangaCategoriesDialog.Listener, - DeleteLibraryMangasDialog.Listener { + DeleteLibraryMangasDialog.Listener, + MigrationInterface { /** * Position of the active category. @@ -78,6 +90,11 @@ class LibraryController( */ val selectedMangas = mutableSetOf() + /** + * Current mangas to move. + */ + private var migratingMangas = mutableSetOf() + private var selectedCoverManga: Manga? = null /** @@ -95,6 +112,11 @@ class LibraryController( */ val libraryMangaRelay: BehaviorRelay = BehaviorRelay.create() + /** + * Relay to notify the library's viewpager to select all manga + */ + val selectAllRelay: PublishRelay = PublishRelay.create() + /** * Number of manga per row in grid mode. */ @@ -425,11 +447,36 @@ class LibraryController( } R.id.action_move_to_category -> showChangeMangaCategoriesDialog() R.id.action_delete -> deleteMangasFromLibrary() + R.id.action_select_all -> { + adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let { + selectAllRelay.call(it) + } + } + R.id.action_migrate -> startMangaMigration() else -> return false } return true } + override fun migrateManga(prevManga: Manga, manga: Manga, replace: Boolean): Manga? { + presenter.migrateManga(prevManga, manga, replace = replace) + val nextManga = migratingMangas.firstOrNull() ?: return null + migratingMangas.remove(nextManga) + return nextManga + } + + private fun startMangaMigration() { + migratingMangas.clear() + migratingMangas.addAll(selectedMangas) + destroyActionModeIfNeeded() + val manga = migratingMangas.firstOrNull() ?: return + val searchController = SearchController(manga) + searchController.totalProgress = migratingMangas.size + searchController.targetController = this + router.pushController(searchController.withFadeTransaction()) + migratingMangas.remove(manga) + } + override fun onDestroyActionMode(mode: ActionMode?) { // Clear all the manga selections and notify child views. selectedMangas.clear() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 1c1b6fd182..c55470500b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -11,12 +11,16 @@ import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.LocalSource +import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.ui.migration.MigrationFlags import eu.kanade.tachiyomi.util.combineLatest import eu.kanade.tachiyomi.util.isNullOrUnsubscribed +import eu.kanade.tachiyomi.util.syncChaptersWithSource import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers @@ -355,6 +359,79 @@ class LibraryPresenter( db.setMangaCategories(mc, mangas) } + fun migrateManga(prevManga: Manga, manga: Manga, replace: Boolean) { + val source = sourceManager.get(manga.source) ?: return + + //state = state.copy(isReplacingManga = true) + + Observable.defer { source.fetchChapterList(manga) } + .onErrorReturn { emptyList() } + .doOnNext { migrateMangaInternal(source, it, prevManga, manga, replace) } + .onErrorReturn { emptyList() } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + //.doOnUnsubscribe { state = state.copy(isReplacingManga = false) } + .subscribe() + } + + private fun migrateMangaInternal(source: Source, sourceChapters: List, + prevManga: Manga, manga: Manga, replace: Boolean) { + + val flags = preferences.migrateFlags().getOrDefault() + val migrateChapters = MigrationFlags.hasChapters(flags) + val migrateCategories = MigrationFlags.hasCategories(flags) + val migrateTracks = MigrationFlags.hasTracks(flags) + + db.inTransaction { + // Update chapters read + if (migrateChapters) { + try { + syncChaptersWithSource(db, sourceChapters, manga, source) + } catch (e: Exception) { + // Worst case, chapters won't be synced + } + + val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking() + val maxChapterRead = + prevMangaChapters.filter { it.read }.maxBy { it.chapter_number }?.chapter_number + if (maxChapterRead != null) { + val dbChapters = db.getChapters(manga).executeAsBlocking() + for (chapter in dbChapters) { + if (chapter.isRecognizedNumber && chapter.chapter_number <= maxChapterRead) { + chapter.read = true + } + } + db.insertChapters(dbChapters).executeAsBlocking() + } + } + // Update categories + if (migrateCategories) { + val categories = db.getCategoriesForManga(prevManga).executeAsBlocking() + val mangaCategories = categories.map { MangaCategory.create(manga, it) } + db.setMangaCategories(mangaCategories, listOf(manga)) + } + // Update track + if (migrateTracks) { + val tracks = db.getTracks(prevManga).executeAsBlocking() + for (track in tracks) { + track.id = null + track.manga_id = manga.id!! + } + db.insertTracks(tracks).executeAsBlocking() + } + // Update favorite status + if (replace) { + prevManga.favorite = false + db.updateMangaFavorite(prevManga).executeAsBlocking() + } + manga.favorite = true + db.updateMangaFavorite(manga).executeAsBlocking() + + // SearchPresenter#networkToLocalManga may have updated the manga title, so ensure db gets updated title + db.updateMangaTitle(manga).executeAsBlocking() + } + } + /** * Update cover with local file. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt index c1c3496aa1..323b905e06 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.migration import android.app.Dialog import android.os.Bundle -import androidx.recyclerview.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -20,7 +19,8 @@ import kotlinx.android.synthetic.main.migration_controller.* class MigrationController : NucleusController(), FlexibleAdapter.OnItemClickListener, - SourceAdapter.OnSelectClickListener { + SourceAdapter.OnSelectClickListener, + MigrationInterface { private var adapter: FlexibleAdapter>? = null @@ -38,6 +38,13 @@ class MigrationController : NucleusController(), return inflater.inflate(R.layout.migration_controller, container, false) } + fun searchController(manga:Manga): SearchController { + val controller = SearchController(manga) + controller.targetController = this + + return controller + } + override fun onViewCreated(view: View) { super.onViewCreated(view) @@ -112,12 +119,9 @@ class MigrationController : NucleusController(), onItemClick(view, position) } - fun migrateManga(prevManga: Manga, manga: Manga) { - presenter.migrateManga(prevManga, manga, replace = true) - } - - fun copyManga(prevManga: Manga, manga: Manga) { - presenter.migrateManga(prevManga, manga, replace = false) + override fun migrateManga(prevManga: Manga, manga: Manga, replace: Boolean): Manga? { + presenter.migrateManga(prevManga, manga, replace) + return null } class LoadingController : DialogController() { @@ -135,4 +139,8 @@ class MigrationController : NucleusController(), const val LOADING_DIALOG_TAG = "LoadingDialog" } -} \ No newline at end of file +} + +interface MigrationInterface { + fun migrateManga(prevManga: Manga, manga: Manga, replace: Boolean): Manga? +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt index 275d3a911a..8db47740e7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt @@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchPresenter import uy.kohesive.injekt.injectLazy @@ -17,6 +18,16 @@ class SearchController( ) : CatalogueSearchController(manga?.title) { private var newManga: Manga? = null + private var progress = 1 + var totalProgress = 0 + + override fun getTitle(): String? { + if (totalProgress > 1) { + return "($progress/$totalProgress) ${super.getTitle()}" + } + else + return super.getTitle() + } override fun createPresenter(): CatalogueSearchPresenter { return SearchPresenter(initialQuery, manga!!) @@ -35,21 +46,32 @@ class SearchController( } fun migrateManga() { - val target = targetController as? MigrationController ?: return + val target = targetController as? MigrationInterface ?: return val manga = manga ?: return val newManga = newManga ?: return - router.popController(this) - target.migrateManga(manga, newManga) + val nextManga = target.migrateManga(manga, newManga, true) + replaceWithNewSearchController(nextManga) } fun copyManga() { - val target = targetController as? MigrationController ?: return + val target = targetController as? MigrationInterface ?: return val manga = manga ?: return val newManga = newManga ?: return - router.popController(this) - target.copyManga(manga, newManga) + val nextManga = target.migrateManga(manga, newManga, false) + replaceWithNewSearchController(nextManga) + } + + private fun replaceWithNewSearchController(manga: Manga?) { + if (manga != null) { + router.popCurrentController() + val searchController = SearchController(manga) + searchController.targetController = targetController + searchController.progress = progress + 1 + searchController.totalProgress = totalProgress + router.replaceTopController(searchController.withFadeTransaction()) + } else router.popController(this) } override fun onMangaClick(manga: Manga) { diff --git a/app/src/main/res/drawable-hdpi/baseline_swap_calls_white_18.png b/app/src/main/res/drawable-hdpi/baseline_swap_calls_white_18.png new file mode 100644 index 0000000000000000000000000000000000000000..fd853dfb6d727fc3d8b201c3330cd9d39802af5a GIT binary patch literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^(jd&i0wmS%+S~(D`#oJ8Ln;{Go>uf=PGn%akiSWB zb<*{F&3cg`7Z%92tUi5faZ}h^?$@CkBXrksx0N1LTj4jaXimY?<61fE_n#4Fc0T^C ziQd=r#AX^GS{pUvYkF7(ig<(WB>4iHRg%C w;ET()Uc0gCmXsGvDuk z_xyRH?!TmK?SzxH?u~tJ9_0*G0H_SJeF7#WrZ10v&J-zk4&Y1Ay`E2SaF;P9N*^3G zuXocCJZ4OZG6t(iS%GoR6etU@_|4DXg=(mV3@k3s7HqHAAi@kRBV`F@x1pA!yrWix zC-4y|@8CJ2OeH45gEJV#Pe$N;S<6&nE_ns)yx0NWA}^;BlhUvU0PHm)id14!nl>sx pWuqD8w6)_#I;Iw;I+0gb_YD{MNsoO6AvFL1002ovPDHLkV1m}lZ=3)C literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/baseline_swap_calls_white_36.png b/app/src/main/res/drawable-hdpi/baseline_swap_calls_white_36.png new file mode 100644 index 0000000000000000000000000000000000000000..b36eb4ff9766ba01490470fc39d9a7a8f27959c1 GIT binary patch literal 426 zcmV;b0agBqP)B(YJ!kqh=F0qRL}xj z|M1+$V>`Y9?EM~aoWI9O&|!jr33hp;LX9F9tk5k6MtNpb+Cd-ZH1L&KGE!xr+(wQ8 z-e{&l%1F^hj$ZP#QfJvn#m})%gaT(Aamx?ti+&>&FUJ5i)DB(Iu@q1TMk-#86zbHQ zkMoQ3ZlvPn$e;$r!!c^uNX5xkVA!#toW^oYsGX-d&e5h9K3Ny!t}NN>p1OKnbF%!YZyHK-PXFkyUhXbnv%luh z!5f75YA6xSSlz9I>?B(&NbwwZi_L0Zh+l{4VKB7BW54B@}V&$|cJ_&pnC9 zrXH|ZHuGGe&!G>u%>_jqQP2~)Bb49u_;|vU6NYbsQ{s;)Y6dfIdtu}=eN~Th(6b%itW{F)|7o`= jO#VLs7-)(u_Ag~M!)1R+goU{QBZa}!)z4*}Q$iB}NaVcS literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/baseline_swap_calls_white_18.png b/app/src/main/res/drawable-mdpi/baseline_swap_calls_white_18.png new file mode 100644 index 0000000000000000000000000000000000000000..2d77978c6f8a14048840dc19faf9b43da0a5aace GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+0wn(&ce?|mCVRR#hEy<~J;k_;iBZD!;r(ij z4h{h(1qba89~Ot(D|B0Kd2uLcG_o+dFf}zY39wGoKX%~?+pC7+^}_K^N3R@>)4yLT z{q_5k^ViPaIOJ^Z9kirtrW%`|mtR`tBjw9()|ET()Uc0gCmXsGvDuk z_xyRH?!TmK?SzxH?u~tJ9_0*G0H_SJeF7#WrZ10v&J-zk4&Y1Ay`E2SaF;P9N*^3G zuXocCJZ4OZG6t(iS%GoR6etU@_|4DXg=(mV3@k3s7HqHAAi@kRBV`F@x1pA!yrWix zC-4y|@8CJ2OeH45gEJV#Pe$N;S<6&nE_ns)yx0NWA}^;BlhUvU0PHm)id14!nl>sx pWuqD8w6)_#I;Iw;I+0gb_YD{MNsoO6AvFL1002ovPDHLkV1m}lZ=3)C literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/baseline_swap_calls_white_48.png b/app/src/main/res/drawable-mdpi/baseline_swap_calls_white_48.png new file mode 100644 index 0000000000000000000000000000000000000000..106a5f05709629920b5a1151ceb23e7ac1f5d19b GIT binary patch literal 323 zcmV-J0lfZ+P)3ros zyYK7fyn2_xs?H*MiwNQsXdS51ffHaI6~s#1tp;!~b)|3W z0BGFA^P@AwCOT&#M23_?B}Ap@g-M-)N>AS=<)bnoK0aoR-Px)gZ3CnD&ymSwJ^@%_ Vvme?Csa^m8002ovPDHLkV1nPnhByEK literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_18.png new file mode 100644 index 0000000000000000000000000000000000000000..baf96b8d9ab68f2cf01a831982684a2c23a6e623 GIT binary patch literal 291 zcmV+;0o?wHP)ET()Uc0gCmXsGvDuk z_xyRH?!TmK?SzxH?u~tJ9_0*G0H_SJeF7#WrZ10v&J-zk4&Y1Ay`E2SaF;P9N*^3G zuXocCJZ4OZG6t(iS%GoR6etU@_|4DXg=(mV3@k3s7HqHAAi@kRBV`F@x1pA!yrWix zC-4y|@8CJ2OeH45gEJV#Pe$N;S<6&nE_ns)yx0NWA}^;BlhUvU0PHm)id14!nl>sx pWuqD8w6)_#I;Iw;I+0gb_YD{MNsoO6AvFL1002ovPDHLkV1m}lZ=3)C literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_24.png new file mode 100644 index 0000000000000000000000000000000000000000..106a5f05709629920b5a1151ceb23e7ac1f5d19b GIT binary patch literal 323 zcmV-J0lfZ+P)3ros zyYK7fyn2_xs?H*MiwNQsXdS51ffHaI6~s#1tp;!~b)|3W z0BGFA^P@AwCOT&#M23_?B}Ap@g-M-)N>AS=<)bnoK0aoR-Px)gZ3CnD&ymSwJ^@%_ Vvme?Csa^m8002ovPDHLkV1nPnhByEK literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_36.png new file mode 100644 index 0000000000000000000000000000000000000000..74584ecabd3dac30c47fc7ea50513eacf4654ed0 GIT binary patch literal 443 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXoKNz}V#J;uuoF`1Yo*hjXDw+sEz7 zO*cXW(gm%5+?;H&!TfDq+1u?>K3Ny!t}NN>p1OKnbF%!YZyHK-PXFkyUhXbnv%luh z!5f75YA6xSSlz9I>?B(&NbwwZi_L0Zh+l{4VKB7BW54B@}V&$|cJ_&pnC9 zrXH|ZHuGGe&!G>u%>_jqQP2~)Bb49u_;|vU6NYbsQ{s;)Y6dfIdtu}=eN~Th(6b%itW{F)|7o`= jO#VLs7-)(u_Ag~M!)1R+goU{QBZa}!)z4*}Q$iB}NaVcS literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_swap_calls_white_48.png new file mode 100644 index 0000000000000000000000000000000000000000..2de9d7969df599222fa3adae8a2a0175aa6d7947 GIT binary patch literal 580 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7z{Kt8;uuoF`1Y1+g^YuU>qAcC z$$Bp)>EAdqWl!E7jmg@t7U@;SuhYC`P__Au-`D6F`Q=9UgTHTYtUdnjj)D>hOlnfp z``EbuP2l1~cK<6*r?NR4y(_l=k}Nvf*=2-YJQY(-^18Fg{Ao=)%d#Ji z)^!F~U;gCdlu4akmRr1I@@HA08L91lZwzj~1B&u|Z1?+{xMD9*w8EpSz4Q5Vzl3>O zz27PhMXJqwBIAE!ap2U}A3yy#_biH==v^}N{>w)~uCMm?&3`}1!CrKY)NyCwISblC z7uwhDb7tzk63wSu&|1~~5oBE7R`2qR#=No(aYxRVdpr=nc2?k^?;3xQT*Of;Q6-Dc zty1>)6&sDNRdgiCtQG;X8FilD_g~Jys^P%M70|#WvH+baxO0Ea(uxK8&E1NQ*VgZk zJZ>eaWYM@)?$XoBh6mc$dIb*hu34`bJ5OC9F5&GZY03UKNqc!-ezG~V@yfx)4~)J} zbJ}Hde!-XEW2;Q-r#%XJ5_wJaVI4dFV{s|DWBNzrj|HdBVA^mYY1W4+#%GMAXR4iP zFR?r>VWV_(@r3YSGHr@=Pv<{Bk}9WSc)ILgV@S+1PYL%MXRHG^%eYngeAIpKaiM62 z>!s_*d_GIVJx#|9_@(JTP@Ic)I$z JtaD0e0szFK1GoSH literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_18.png new file mode 100644 index 0000000000000000000000000000000000000000..b36eb4ff9766ba01490470fc39d9a7a8f27959c1 GIT binary patch literal 426 zcmV;b0agBqP)B(YJ!kqh=F0qRL}xj z|M1+$V>`Y9?EM~aoWI9O&|!jr33hp;LX9F9tk5k6MtNpb+Cd-ZH1L&KGE!xr+(wQ8 z-e{&l%1F^hj$ZP#QfJvn#m})%gaT(Aamx?ti+&>&FUJ5i)DB(Iu@q1TMk-#86zbHQ zkMoQ3ZlvPn$e;$r!!c^uNX5xkVA!#toW^oYsGX-d&e5h9K3Ny!t}NN>p1OKnbF%!YZyHK-PXFkyUhXbnv%luh z!5f75YA6xSSlz9I>?B(&NbwwZi_L0Zh+l{4VKB7BW54B@}V&$|cJ_&pnC9 zrXH|ZHuGGe&!G>u%>_jqQP2~)Bb49u_;|vU6NYbsQ{s;)Y6dfIdtu}=eN~Th(6b%itW{F)|7o`= jO#VLs7-)(u_Ag~M!)1R+goU{QBZa}!)z4*}Q$iB}NaVcS literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_36.png new file mode 100644 index 0000000000000000000000000000000000000000..b37a98febcf694da726880f3d852afbfd9504539 GIT binary patch literal 740 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz0wh)Q=esd5Fs=43 z;Kl`k&V9a*awjcbc0}iZO|R9l8_PG?9$TTSdD^PiY@6lm+*_B@W-h;YR4~2VC4837 zXA`-=J^w@^w`ImWp7BVw*w%GgtQ2p~#B=^enw!>KnxVe;r%0q(<{gE5dh2)ia*Jm^ zYdhe`BBwOYhf%G|Arr}4qAL+Dj-r&D@?~Gb^`@&m?BcEmZ2z_-C`Z#69$%1K> zQmZrKmn!UAu(oY;&*c*WR~1<&s=msyIBn9ab4#ByiCb6toRRNh>9=!PK8mfio|8K3 zn8K|oEQYOSD>lEmd@26UxBWI}4kM#WpAGndh#Nv7kyR3&72Fxzottfonq+RRU@`16 zQ(3yOlhRi~@$YnQKG zGnT*9>8<)FwAIN?DI;O(iux zMUU4r%iZ5Yx{@Y{O&2}J+GeTnrXlf^i=l`2Ij+ZC=WnXtlv{kID`~RW39iRR-+y|{ zyZou<0poNRLvQcdOD~?#eP`s*$N27|=VA+R`T-N=d4JeTj?YM6vS#rlVCrS?boFyt I=akR{01_ZeRsaA1 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_swap_calls_white_48.png new file mode 100644 index 0000000000000000000000000000000000000000..b2521cdd1d5211d30d96333c2d9d0c90fd404ff3 GIT binary patch literal 872 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q1xWh(YZ)^zFzb7|IEGX(zP)ScF*Q--*vHEg zuK7x5t#e9}r5Qmp{Mgo|MmMiId-IBn2H!5zYcm91OvqZIo7QNRQSf{F zm2dm5|E}zx!(UZrUH&6qeBb9i*K`Dt!9%vYd!E>~|0zDezU;-bwz&$&BsLc&bZq5w?&dju zfBdDNXn*b5{iM_1MSAy>vqi^@EDlG1D$6WCAw0iB@zb)m96l4xpG*K6E`M_7^C_~8 z!Dl9J2J)>0#ZTN^lEk~D-Xa|JGMbE*}WEZ2DQ;wDYL(9$VA;!o^uzHuWq|jXHa3PKHih-i7!N z8K3Ny!t}NN>p1OKnbF%!YZyHK-PXFkyUhXbnv%luh z!5f75YA6xSSlz9I>?B(&NbwwZi_L0Zh+l{4VKB7BW54B@}V&$|cJ_&pnC9 zrXH|ZHuGGe&!G>u%>_jqQP2~)Bb49u_;|vU6NYbsQ{s;)Y6dfIdtu}=eN~Th(6b%itW{F)|7o`= jO#VLs7-)(u_Ag~M!)1R+goU{QBZa}!)z4*}Q$iB}NaVcS literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_24.png new file mode 100644 index 0000000000000000000000000000000000000000..2de9d7969df599222fa3adae8a2a0175aa6d7947 GIT binary patch literal 580 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7z{Kt8;uuoF`1Y1+g^YuU>qAcC z$$Bp)>EAdqWl!E7jmg@t7U@;SuhYC`P__Au-`D6F`Q=9UgTHTYtUdnjj)D>hOlnfp z``EbuP2l1~cK<6*r?NR4y(_l=k}Nvf*=2-YJQY(-^18Fg{Ao=)%d#Ji z)^!F~U;gCdlu4akmRr1I@@HA08L91lZwzj~1B&u|Z1?+{xMD9*w8EpSz4Q5Vzl3>O zz27PhMXJqwBIAE!ap2U}A3yy#_biH==v^}N{>w)~uCMm?&3`}1!CrKY)NyCwISblC z7uwhDb7tzk63wSu&|1~~5oBE7R`2qR#=No(aYxRVdpr=nc2?k^?;3xQT*Of;Q6-Dc zty1>)6&sDNRdgiCtQG;X8FilD_g~Jys^P%M70|#WvH+baxO0Ea(uxK8&E1NQ*VgZk zJZ>eaWYM@)?$XoBh6mc$dIb*hu34`bJ5OC9F5&GZY03UKNqc!-ezG~V@yfx)4~)J} zbJ}Hde!-XEW2;Q-r#%XJ5_wJaVI4dFV{s|DWBNzrj|HdBVA^mYY1W4+#%GMAXR4iP zFR?r>VWV_(@r3YSGHr@=Pv<{Bk}9WSc)ILgV@S+1PYL%MXRHG^%eYngeAIpKaiM62 z>!s_*d_GIVJx#|9_@(JTP@Ic)I$z JtaD0e0szFK1GoSH literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_swap_calls_white_36.png new file mode 100644 index 0000000000000000000000000000000000000000..b2521cdd1d5211d30d96333c2d9d0c90fd404ff3 GIT binary patch literal 872 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q1xWh(YZ)^zFzb7|IEGX(zP)ScF*Q--*vHEg zuK7x5t#e9}r5Qmp{Mgo|MmMiId-IBn2H!5zYcm91OvqZIo7QNRQSf{F zm2dm5|E}zx!(UZrUH&6qeBb9i*K`Dt!9%vYd!E>~|0zDezU;-bwz&$&BsLc&bZq5w?&dju zfBdDNXn*b5{iM_1MSAy>vqi^@EDlG1D$6WCAw0iB@zb)m96l4xpG*K6E`M_7^C_~8 z!Dl9J2J)>0#ZTN^lEk~D-Xa|JGMbE*}WEZ2DQ;wDYL(9$VA;!o^uzHuWq|jXHa3PKHih-i7!N z8< zLqC1~Oxx@Yo9YbL{fjR!O{}nq2yr31U=OY34Odx17^^CRw~Jl~3AY(saosJNS;NpUKx} zY+Us3nS|FS-YFJs`%T*w7$kfgX6kiGJgqwB$#<;KR$1htr)6!OGUtv4C94~;TnYYG z8jqU3{OnbEVEt%cYNN;zrG2XJc7OTltCC<`_}?IU)d87*ih04m{;&xZ7#lX{Ow!ue z%9xa=XSe?$OO4Z+${^-*%FiA@`aIkBfJxH7B=MDuyFaKKUhX=dZ^GEF{qIVZjG_CH z=jQVo9QGxaO_d5vno*;eTgS{5d(|Jg_v~}N~z&(C(CyNxylwY*RCi#ws&s} zvu8f4lJsxQPoHb?M|=b}&Q-YbG~f=am%4|&VC~v^t_ia{B@?PBio0KA|4p8e zqxeq#nTP0%^Y%w_1#90H@J-9__&tj?NPzptvL8ERW^+0T^SizGV|R_w_;u^CibblG zX3~_^i`6f$Pn)8&OQZXS_k#Mq|M`6jRci~;i;fxx*M76h1$(yWHJ$n+m{Q}mxW-W}N#AjTiq7)sZZA@2Zm|MM z$efV4b?ip`Ek?)Ge;j_!w>2;6acF&ZFJPXvZhDzhz)brl_KTk;Y>{p{1T@5^t4;lc z%NkXVMGZaGE4Tmt`aHj;Ng>N(j^3-KvzwRB6%2XSpP(nI5Zik5(mRkb6AFcxm%MnK zVzjYgfk{2f=bg)sas0h=*k)t%0<(G+;hhcrD~=tXbKYfR+XAb47Vn*Nwo53TR}j@p zUK!!4;1Rr0xw=4S`zNdSpN*Y)K5@%`klJ1(Q@vqvPA)$mC#WQ1`CI>%%^FrHL1`Zr X{ + + diff --git a/app/src/main/res/menu/library_selection.xml b/app/src/main/res/menu/library_selection.xml index 357acfe48c..728135e460 100644 --- a/app/src/main/res/menu/library_selection.xml +++ b/app/src/main/res/menu/library_selection.xml @@ -18,4 +18,15 @@ android:icon="@drawable/ic_delete_white_24dp" app:showAsAction="ifRoom"/> + + + + \ No newline at end of file