From 159f7f996101aecc139fb8cd4624a97a6de10cc2 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Tue, 28 Jun 2022 19:25:50 -0300 Subject: [PATCH 01/28] =?UTF-8?q?Corrigido=20erro=20na=20ordena=C3=A7?= =?UTF-8?q?=C3=A3o=20da=20pagina=20dupla,=20no=20qual=20em=20alguns=20caso?= =?UTF-8?q?s=20inseria=20a=20imagem=20errada=20no=20lado=20direito.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/entity/PageLink.kt | 207 +++++++++++++++--- .../view/ui/pages_link/PagesLinkViewModel.kt | 31 ++- 2 files changed, 197 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt index 970e00f8..712ca326 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt @@ -10,42 +10,150 @@ import java.io.Serializable tableName = DataBaseConsts.PAGESLINK.TABLE_NAME, indices = [Index(value = [DataBaseConsts.PAGESLINK.COLUMNS.FK_ID_FILE])] ) -class PageLink(id: Long?, idFile: Long?, mangaPage: Int, mangaPages: Int, mangaPageName: String, mangaPagePath: String, fileLinkPage: Int = PageLinkConsts.VALUES.PAGE_EMPTY, - fileLinkPages: Int = 0, fileLinkPageName: String = "", fileLinkPagePath: String = "", fileRightLinkPage: Int = PageLinkConsts.VALUES.PAGE_EMPTY, - fileRightLinkPageName: String = "", fileRightLinkPagePath: String = "", notLinked: Boolean = false, dualImage: Boolean = false, isMangaDualPage: Boolean = false, - isFileLeftDualPage: Boolean = false, isFileRightDualPage: Boolean = false) : Serializable { - - constructor(id: Long?, idFile: Long?, mangaPage: Int, mangaPages: Int, mangaPageName: String, mangaPagePath: String, fileLinkPage: Int, fileLinkPages: Int, - fileLinkPageName: String, fileLinkPagePath: String, fileRightLinkPage: Int, fileRightLinkPageName: String, fileRightLinkPagePath: String, - notLinked: Boolean, dualImage: Boolean, isMangaDualPage: Boolean, isFileLeftDualPage: Boolean, isFileRightDualPage: Boolean, imageMangaPage: Bitmap? = null, - imageFileLinkPage: Bitmap? = null, imageRightFileLinkPage: Bitmap? = null - ) : this(id, idFile, mangaPage, mangaPages, mangaPageName, mangaPagePath, fileLinkPage, fileLinkPages, fileLinkPageName, fileLinkPagePath, fileRightLinkPage, - fileRightLinkPageName, fileRightLinkPagePath, notLinked, dualImage, isMangaDualPage, isFileLeftDualPage, isFileRightDualPage) { +class PageLink( + id: Long?, + idFile: Long?, + mangaPage: Int, + mangaPages: Int, + mangaPageName: String, + mangaPagePath: String, + fileLinkPage: Int = PageLinkConsts.VALUES.PAGE_EMPTY, + fileLinkPages: Int = 0, + fileLinkPageName: String = "", + fileLinkPagePath: String = "", + fileRightLinkPage: Int = PageLinkConsts.VALUES.PAGE_EMPTY, + fileRightLinkPageName: String = "", + fileRightLinkPagePath: String = "", + notLinked: Boolean = false, + dualImage: Boolean = false, + isMangaDualPage: Boolean = false, + isFileLeftDualPage: Boolean = false, + isFileRightDualPage: Boolean = false +) : Serializable { + + constructor( + id: Long?, + idFile: Long?, + mangaPage: Int, + mangaPages: Int, + mangaPageName: String, + mangaPagePath: String, + fileLinkPage: Int, + fileLinkPages: Int, + fileLinkPageName: String, + fileLinkPagePath: String, + fileRightLinkPage: Int, + fileRightLinkPageName: String, + fileRightLinkPagePath: String, + notLinked: Boolean, + dualImage: Boolean, + isMangaDualPage: Boolean, + isFileLeftDualPage: Boolean, + isFileRightDualPage: Boolean, + imageMangaPage: Bitmap? = null, + imageFileLinkPage: Bitmap? = null, + imageRightFileLinkPage: Bitmap? = null + ) : this( + id, + idFile, + mangaPage, + mangaPages, + mangaPageName, + mangaPagePath, + fileLinkPage, + fileLinkPages, + fileLinkPageName, + fileLinkPagePath, + fileRightLinkPage, + fileRightLinkPageName, + fileRightLinkPagePath, + notLinked, + dualImage, + isMangaDualPage, + isFileLeftDualPage, + isFileRightDualPage + ) { this.imageMangaPage = imageMangaPage this.imageLeftFileLinkPage = imageFileLinkPage this.imageRightFileLinkPage = imageRightFileLinkPage } - constructor(idFile: Long?, mangaPage: Int, mangaPages: Int, mangaPageName: String, mangaPagePath: String, fileLinkPage: Int, fileLinkPages: Int, fileLinkPageName: String, - fileLinkPagePath: String, isFileLeftDualPage: Boolean, isFileRightDualPage: Boolean, imageFileLinkPage: Bitmap? = null, imageRightFileLinkPage: Bitmap? = null - ) : this(null, idFile, mangaPage, mangaPages, mangaPageName, mangaPagePath, fileLinkPage, fileLinkPages, fileLinkPageName, fileLinkPagePath, - notLinked = mangaPage == PageLinkConsts.VALUES.PAGE_EMPTY, isFileLeftDualPage = isFileLeftDualPage, isFileRightDualPage = isFileRightDualPage) { + constructor( + idFile: Long?, + mangaPage: Int, + mangaPages: Int, + mangaPageName: String, + mangaPagePath: String, + fileLinkPage: Int, + fileLinkPages: Int, + fileLinkPageName: String, + fileLinkPagePath: String, + isFileLeftDualPage: Boolean, + isFileRightDualPage: Boolean, + imageFileLinkPage: Bitmap? = null, + imageRightFileLinkPage: Bitmap? = null + ) : this( + null, + idFile, + mangaPage, + mangaPages, + mangaPageName, + mangaPagePath, + fileLinkPage, + fileLinkPages, + fileLinkPageName, + fileLinkPagePath, + notLinked = mangaPage == PageLinkConsts.VALUES.PAGE_EMPTY, + isFileLeftDualPage = isFileLeftDualPage, + isFileRightDualPage = isFileRightDualPage + ) { this.imageMangaPage = null this.imageLeftFileLinkPage = imageFileLinkPage this.imageRightFileLinkPage = imageRightFileLinkPage } - constructor(idFile: Long?, mangaPage: Int, mangaPages: Int, mangaPageName: String, mangaPagePath: String, isMangaDualPage: Boolean = false, imageMangaPage: Bitmap? = null + constructor( + idFile: Long?, + mangaPage: Int, + mangaPages: Int, + mangaPageName: String, + mangaPagePath: String, + isMangaDualPage: Boolean = false, + imageMangaPage: Bitmap? = null ) : this(null, idFile, mangaPage, mangaPages, mangaPageName, mangaPagePath, isMangaDualPage = isMangaDualPage) { this.imageMangaPage = imageMangaPage this.imageLeftFileLinkPage = null this.imageRightFileLinkPage = null } - constructor(idFile: Long?, mangaPage: Int, mangaPages: Int, mangaPageName: String, mangaPagePath: String, fileLinkPage: Int, fileLinkPages: Int, - fileLinkPageName: String, fileLinkPagePath: String, notLinked:Boolean = false, isMangaDualPage: Boolean = false, isFileLeftDualPage: Boolean = false, - imageMangaPage: Bitmap? = null, imageFileLinkPage: Bitmap? = null - ) : this(null, idFile, mangaPage, mangaPages, mangaPageName, mangaPagePath, fileLinkPage, fileLinkPages, fileLinkPageName, fileLinkPagePath, notLinked = notLinked) { + constructor( + idFile: Long?, + mangaPage: Int, + mangaPages: Int, + mangaPageName: String, + mangaPagePath: String, + fileLinkPage: Int, + fileLinkPages: Int, + fileLinkPageName: String, + fileLinkPagePath: String, + notLinked: Boolean = false, + isMangaDualPage: Boolean = false, + isFileLeftDualPage: Boolean = false, + imageMangaPage: Bitmap? = null, + imageFileLinkPage: Bitmap? = null + ) : this( + null, + idFile, + mangaPage, + mangaPages, + mangaPageName, + mangaPagePath, + fileLinkPage, + fileLinkPages, + fileLinkPageName, + fileLinkPagePath, + notLinked = notLinked + ) { this.imageMangaPage = imageMangaPage this.imageLeftFileLinkPage = imageFileLinkPage this.imageRightFileLinkPage = null @@ -53,10 +161,13 @@ class PageLink(id: Long?, idFile: Long?, mangaPage: Int, mangaPages: Int, mangaP this.isFileLeftDualPage = isFileLeftDualPage } - constructor(idFile: Long?, notLinked:Boolean, fileLinkPage: Int, fileLinkPages: Int, fileLinkPageName: String, fileLinkPagePath: String, - isFileLeftDualPage: Boolean = false, imageFileLinkPage: Bitmap? = null - ) : this(null, idFile, PageLinkConsts.VALUES.PAGE_EMPTY, 0, "", "", fileLinkPage, fileLinkPages, - fileLinkPageName, fileLinkPagePath, notLinked = notLinked) { + constructor( + idFile: Long?, notLinked: Boolean, fileLinkPage: Int, fileLinkPages: Int, fileLinkPageName: String, fileLinkPagePath: String, + isFileLeftDualPage: Boolean = false, imageFileLinkPage: Bitmap? = null + ) : this( + null, idFile, PageLinkConsts.VALUES.PAGE_EMPTY, 0, "", "", fileLinkPage, fileLinkPages, + fileLinkPageName, fileLinkPagePath, notLinked = notLinked + ) { this.imageMangaPage = null this.imageLeftFileLinkPage = imageFileLinkPage this.imageRightFileLinkPage = null @@ -66,44 +177,64 @@ class PageLink(id: Long?, idFile: Long?, mangaPage: Int, mangaPages: Int, mangaP @PrimaryKey(autoGenerate = true) @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.ID) var id: Long? = id + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FK_ID_FILE) var idFile: Long? = idFile + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.MANGA_PAGE) val mangaPage: Int = mangaPage + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.MANGA_PAGES) val mangaPages: Int = mangaPages + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.MANGA_PAGE_NAME) val mangaPageName: String = mangaPageName + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.MANGA_PAGE_PATH) val mangaPagePath: String = mangaPagePath + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_LINK_PAGE) var fileLinkPage: Int = fileLinkPage + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_LINK_PAGES) var fileLinkPages: Int = fileLinkPages + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_LINK_PAGE_NAME) var fileLinkPageName: String = fileLinkPageName + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_LINK_PAGE_PATH) var fileLinkPagePath: String = fileLinkPagePath + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_RIGHT_LINK_PAGE) var fileRightLinkPage: Int = fileRightLinkPage + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_RIGHT_LINK_PAGE_NAME) var fileRightLinkPageName: String = fileRightLinkPageName + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_RIGHT_LINK_PAGE_PATH) var fileRightLinkPagePath: String = fileRightLinkPagePath + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.NOT_LINKED) var notLinked: Boolean = notLinked + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.DUAL_IMAGE) var dualImage: Boolean = dualImage + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.MANGA_DUAL_PAGE) var isMangaDualPage: Boolean = isMangaDualPage + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_LEFT_DUAL_PAGE) var isFileLeftDualPage: Boolean = isFileLeftDualPage + @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.FILE_RIGHT_DUAL_PAGE) var isFileRightDualPage: Boolean = isFileRightDualPage + @Ignore var imageMangaPage: Bitmap? = null + @Ignore var imageLeftFileLinkPage: Bitmap? = null + @Ignore var imageRightFileLinkPage: Bitmap? = null @@ -124,8 +255,17 @@ class PageLink(id: Long?, idFile: Long?, mangaPage: Int, mangaPages: Int, mangaP } fun addLeftFileLinkImage(another: PageLink) { - this.addLeftFileLinkImage(another.fileLinkPage, another.fileLinkPages, another.fileLinkPageName, - another.fileLinkPagePath, another.isFileLeftDualPage, another.imageLeftFileLinkPage) + this.addLeftFileLinkImage( + another.fileLinkPage, another.fileLinkPages, another.fileLinkPageName, + another.fileLinkPagePath, another.isFileLeftDualPage, another.imageLeftFileLinkPage + ) + } + + fun addLeftFromRightFileLinkImage(another: PageLink) { + this.addLeftFileLinkImage( + another.fileRightLinkPage, another.fileLinkPages, another.fileRightLinkPageName, + another.fileRightLinkPagePath, another.isFileRightDualPage, another.imageRightFileLinkPage + ) } fun addLeftFileLinkImage(page: Int, pages: Int, pageName: String, pagePath: String, isFileLeftDualPage: Boolean, image: Bitmap?) { @@ -137,9 +277,18 @@ class PageLink(id: Long?, idFile: Long?, mangaPage: Int, mangaPages: Int, mangaP this.isFileLeftDualPage = isFileLeftDualPage } + fun addRightFromLeftFileLinkImage(another: PageLink) { + this.addRightFileLinkImage( + another.fileLinkPage, another.fileLinkPageName, another.fileLinkPagePath, + another.isFileLeftDualPage, another.imageLeftFileLinkPage + ) + } + fun addRightFileLinkImage(another: PageLink) { - this.addRightFileLinkImage(another.fileRightLinkPage, another.fileRightLinkPageName, another.fileRightLinkPagePath, - another.isFileRightDualPage, another.imageRightFileLinkPage) + this.addRightFileLinkImage( + another.fileRightLinkPage, another.fileRightLinkPageName, another.fileRightLinkPagePath, + another.isFileRightDualPage, another.imageRightFileLinkPage + ) } fun addRightFileLinkImage(page: Int, pageName: String, pagePath: String, isFileRightDualPage: Boolean, image: Bitmap?) { @@ -184,7 +333,7 @@ class PageLink(id: Long?, idFile: Long?, mangaPage: Int, mangaPages: Int, mangaP this.dualImage = false } - fun clearLeftFileLink(canMoved: Boolean = false) : Boolean { + fun clearLeftFileLink(canMoved: Boolean = false): Boolean { val moved = if (canMoved && this.fileRightLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { this.fileLinkPage = this.fileRightLinkPage this.fileLinkPageName = this.fileRightLinkPageName diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt index fab9d99d..280be233 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt @@ -55,7 +55,7 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio .getBoolean(GeneralConsts.KEYS.PAGE_LINK.USE_PAGE_PATH_FOR_LINKED, false) fun getMangaName(): String { - return mManga?.fileName?: "" + return mManga?.fileName ?: "" } private fun getParse(path: String): Parse? = @@ -546,7 +546,7 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio val originIndex = mPagesLink.value!!.indexOf(origin) val destinyIndex = mPagesLink.value!!.indexOf(destiny) - destiny.addRightFileLinkImage(origin) + destiny.addRightFromLeftFileLinkImage(origin) origin.clearRightFileLink() notifyMessages(originType, PageLinkConsts.MESSAGES.MESSAGE_PAGES_LINK_ITEM_CHANGE, originIndex) @@ -559,7 +559,7 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio val originIndex = mPagesNotLinked.value!!.indexOf(origin) val destinyIndex = mPagesLink.value!!.indexOf(destiny) - destiny.addRightFileLinkImage(origin) + destiny.addRightFromLeftFileLinkImage(origin) mPagesNotLinked.value!!.remove(origin) notifyMessages(originType, PageLinkConsts.MESSAGES.MESSAGE_PAGES_LINK_IMAGE_REMOVED, originIndex) @@ -576,9 +576,9 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio when { originType != Pages.DUAL_PAGE && destinyType == Pages.LINKED -> destiny.addLeftFileLinkImage(origin) - originType != Pages.DUAL_PAGE && destinyType != Pages.LINKED -> destiny.addRightFileLinkImage(origin) + originType != Pages.DUAL_PAGE && destinyType != Pages.LINKED -> destiny.addRightFromLeftFileLinkImage(origin) originType == Pages.DUAL_PAGE && destinyType == Pages.LINKED -> destiny.addLeftFileLinkImage(origin) - originType == Pages.DUAL_PAGE && destinyType != Pages.LINKED -> destiny.addRightFileLinkImage(origin) + originType == Pages.DUAL_PAGE && destinyType != Pages.LINKED -> destiny.addRightFromLeftFileLinkImage(origin) } notifyMessages(destinyType, PageLinkConsts.MESSAGES.MESSAGE_PAGES_LINK_ITEM_CHANGE, destinyIndex) @@ -771,17 +771,22 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio if (page.dualImage || (isUseDualPageCalculate && page.isFileLeftDualPage)) continue + println("" + index + "||" + padding) + + if ((index + padding) >= pagesLink.size) + break + var next = pagesLink[index + padding] if (next.fileLinkPage == PageLinkConsts.VALUES.PAGE_EMPTY) { do { padding++ - if ((index + padding) > pagesLink.size - 1) + if ((index + padding) >= pagesLink.size) break next = pagesLink[index + padding] } while (next.fileLinkPage == PageLinkConsts.VALUES.PAGE_EMPTY) } - if ((index + padding) > pagesLink.size - 1) + if ((index + padding) >= pagesLink.size) break if (next.dualImage || (isUseDualPageCalculate && page.isFileLeftDualPage)) { @@ -806,7 +811,7 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio padding++ next = pagesLink[index + padding] if (next.fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY && !next.dualImage && !next.isFileLeftDualPage) { - page.addRightFileLinkImage(next) + page.addRightFromLeftFileLinkImage(next) next.clearLeftFileLink() indexChanges.add(index + padding) } else @@ -817,7 +822,7 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio if (next.isFileLeftDualPage) continue else { - page.addRightFileLinkImage(next) + page.addRightFromLeftFileLinkImage(next) next.clearLeftFileLink() indexChanges.addAll(arrayOf(index, index + padding)) } @@ -830,13 +835,13 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio indexChanges.addAll(arrayOf(index, index + padding)) if (next.fileRightLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { - page.addRightFileLinkImage(next) + page.addRightFromLeftFileLinkImage(next) next.clearRightFileLink() } else { padding++ next = pagesLink[index + padding] if (!next.dualImage && next.fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { - page.addRightFileLinkImage(next) + page.addRightFromLeftFileLinkImage(next) next.clearLeftFileLink() indexChanges.add(index + padding) } else @@ -849,6 +854,8 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio } } } + + println("Right: image " + page.fileRightLinkPageName) } for (index in indexChanges) @@ -932,7 +939,7 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio continue indexChanges.addAll(arrayOf(index, index + 1)) - page.addRightFileLinkImage(nextPage) + page.addRightFromLeftFileLinkImage(nextPage) nextPage.clearFileLink() for ((idxNext, next) in pagesLink.withIndex()) { From e78e683f80cc4d4ce5c3fcd9a3030c71f61e47a6 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Tue, 28 Jun 2022 19:28:21 -0300 Subject: [PATCH 02/28] =?UTF-8?q?Adi=C3=A7=C3=A3o=20da=20rotina=20de=20tes?= =?UTF-8?q?te=20automatizado.=20Cria=C3=A7=C3=A3o=20das=20unit=20de=20test?= =?UTF-8?q?e=20do=20manga=20detail,=20pages=20link=20e=20main.=20Ajuste=20?= =?UTF-8?q?nas=20nomenclaturas=20de=20algumas=20id=20e=20inser=C3=A7=C3=A3?= =?UTF-8?q?o=20de=20id=20nos=20fragmentos=20para=20ser=20utilizado=20pela?= =?UTF-8?q?=20rotina=20de=20teste.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 14 + .../bilingualmangareader/MainActivityTest.kt | 253 ++++++++++++++++++ .../custom/CustomMatchers.kt | 52 ++++ .../custom/CustomUtils.kt | 63 +++++ .../bilingualmangareader/utils/TestUtils.kt | 114 ++++++++ .../manga_detail/MangaDetailActivityTest.kt | 91 +++++++ .../ui/pages_link/PagesLinkActivityTest.kt | 127 +++++++++ .../view/ui/reader/ReaderActivityTest.kt | 14 + .../bilingualmangareader/MainActivity.kt | 5 +- .../model/entity/Manga.kt | 16 ++ .../controller/ImageCoverController.kt | 93 +++++-- .../bilingualmangareader/util/helpers/Util.kt | 23 ++ .../view/ui/about/AboutFragment.kt | 2 +- .../view/ui/configuration/ConfigFragment.kt | 7 - .../view/ui/library/LibraryFragment.kt | 12 +- .../ui/manga_detail/MangaDetailActivity.kt | 1 - .../ui/manga_detail/MangaDetailFragment.kt | 3 +- .../view/ui/pages_link/PagesLinkActivity.kt | 1 - .../res/layout-land/fragment_pages_link.xml | 1 + .../res/layout-sw600dp/fragment_about.xml | 1 + .../layout-sw600dp/fragment_manga_detail.xml | 2 +- .../layout-sw600dp/fragment_pages_link.xml | 1 + app/src/main/res/layout/fragment_about.xml | 1 + app/src/main/res/layout/fragment_config.xml | 1 + app/src/main/res/layout/fragment_help.xml | 1 + app/src/main/res/layout/fragment_history.xml | 1 + app/src/main/res/layout/fragment_library.xml | 2 +- .../main/res/layout/fragment_manga_detail.xml | 2 +- .../main/res/layout/fragment_pages_link.xml | 1 + app/src/main/res/layout/fragment_reader.xml | 1 + .../main/res/layout/fragment_reader_page.xml | 1 + app/src/main/res/menu/main_menu.xml | 6 +- 32 files changed, 860 insertions(+), 53 deletions(-) create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/MainActivityTest.kt create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomMatchers.kt create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/utils/TestUtils.kt create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivityTest.kt create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt diff --git a/app/build.gradle b/app/build.gradle index 6eebe9f6..7352c494 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -76,6 +76,20 @@ dependencies { implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.36' implementation 'com.github.tony19:logback-android:2.0.0' + // OCR implementation 'cz.adaptech:tesseract4android:4.1.1' implementation 'com.google.android.gms:play-services-mlkit-text-recognition:18.0.0' + + // TEST + testImplementation 'junit:junit:4.13.2' + androidTestImplementation "androidx.test:core:1.4.0" + androidTestImplementation "androidx.test:runner:1.2.0" + androidTestImplementation "androidx.test:rules:1.2.0" + androidTestImplementation "androidx.test.ext:junit:1.1.3" + androidTestImplementation "androidx.test.ext:truth:1.4.0" + androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0" + androidTestImplementation "androidx.test.espresso:espresso-contrib:3.4.0" + androidTestImplementation "androidx.test.espresso:espresso-intents:3.4.0" + + } \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/MainActivityTest.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/MainActivityTest.kt new file mode 100644 index 00000000..00de6ad2 --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/MainActivityTest.kt @@ -0,0 +1,253 @@ +package br.com.fenix.bilingualmangareader + +import android.content.res.Resources +import android.view.Gravity +import android.view.KeyEvent +import androidx.recyclerview.widget.RecyclerView +import androidx.test.core.app.ActivityScenario +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.Espresso.pressBack +import androidx.test.espresso.action.ViewActions.* +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.DrawerActions +import androidx.test.espresso.contrib.DrawerMatchers.isClosed +import androidx.test.espresso.contrib.NavigationViewActions +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import br.com.fenix.bilingualmangareader.view.ui.about.AboutFragment +import br.com.fenix.bilingualmangareader.view.ui.configuration.ConfigFragment +import br.com.fenix.bilingualmangareader.view.ui.help.HelpFragment +import br.com.fenix.bilingualmangareader.view.ui.history.HistoryFragment +import br.com.fenix.bilingualmangareader.view.ui.library.LibraryFragment +import junit.framework.TestCase.assertTrue +import org.junit.FixMethodOrder +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(AndroidJUnit4::class) +class MainActivityTest { + + @get:Rule + var activityScenarioRule: ActivityScenario = ActivityScenario.launch(MainActivity::class.java) + + private val animationTimer = 600L + + @Test + fun `1_open_screens_in_app`() { + val waiter = CountDownLatch(1) + + // History + onView(withId(R.id.drawer_layout)) + .check(matches(isClosed(Gravity.START))) + .perform(DrawerActions.open()) + + onView(withId(R.id.nav_view)) + .perform(NavigationViewActions.navigateTo(R.id.menu_history)) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is HistoryFragment) + } + + // Configuration + onView(withId(R.id.drawer_layout)) + .check(matches(isClosed(Gravity.START))) + .perform(DrawerActions.open()) + + onView(withId(R.id.nav_view)) + .perform(NavigationViewActions.navigateTo(R.id.menu_configuration)) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is ConfigFragment) + } + + // Help + onView(withId(R.id.drawer_layout)) + .check(matches(isClosed(Gravity.START))) + .perform(DrawerActions.open()) + + onView(withId(R.id.nav_view)) + .perform(NavigationViewActions.navigateTo(R.id.menu_help)) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is HelpFragment) + } + + // About + onView(withId(R.id.drawer_layout)) + .check(matches(isClosed(Gravity.START))) + .perform(DrawerActions.open()) + + onView(withId(R.id.nav_view)) + .perform(NavigationViewActions.navigateTo(R.id.menu_about)) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is AboutFragment) + } + + // Library + onView(withId(R.id.drawer_layout)) + .check(matches(isClosed(Gravity.START))) + .perform(DrawerActions.open()) + + onView(withId(R.id.nav_view)) + .perform(NavigationViewActions.navigateTo(R.id.menu_library)) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is LibraryFragment) + } + + pressBack() + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is AboutFragment) + } + + pressBack() + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is HelpFragment) + } + + pressBack() + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is ConfigFragment) + } + + pressBack() + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is HistoryFragment) + } + + pressBack() + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.main_content_root) + assertTrue(fragment is LibraryFragment) + } + } + + + @Test + fun `2_test_in_library`() { + val waiter = CountDownLatch(1) + activityScenarioRule.recreate() // Re load app + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + onView(withId(R.id.menu_library_grid_type)).perform(click()) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + onView(withId(R.id.menu_library_grid_type)).perform(click()) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + onView(withId(R.id.menu_library_grid_type)).perform(click()) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + onView(withId(R.id.menu_library_list_order)).perform(click()) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + onView(withId(R.id.menu_library_list_order)).perform(click()) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + onView(withId(R.id.menu_library_list_order)).perform(click()) + + waiter.await(animationTimer, TimeUnit.MILLISECONDS) + + activityScenarioRule.onActivity { + val recyclerView = it.findViewById(R.id.library_recycler_view) + val itemCount = recyclerView.adapter?.itemCount ?: 0 + + recyclerView.smoothScrollToPosition(itemCount) + + waiter.await(2, TimeUnit.SECONDS) + + recyclerView.smoothScrollToPosition(0) + + waiter.await(2, TimeUnit.SECONDS) + } + + onView(withId(R.id.menu_library_search)).perform(click()) + + onView( + withId( + Resources.getSystem().getIdentifier( + "search_src_text", + "id", "android" + ) + ) + ).perform(clearText(), typeText("Test")) + .perform(pressKey(KeyEvent.KEYCODE_ENTER)) + + onView( + withId( + Resources.getSystem().getIdentifier( + "search_src_text", + "id", "android" + ) + ) + ).perform(clearText()) + .perform(pressKey(KeyEvent.KEYCODE_ENTER)) + + onView( + withId( + Resources.getSystem().getIdentifier( + "search_close_btn", + "id", "android" + ) + ) + ).perform(click()) + + onView( + withId( + Resources.getSystem().getIdentifier( + "search_close_btn", + "id", "android" + ) + ) + ).perform(closeSoftKeyboard()) + } + + +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomMatchers.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomMatchers.kt new file mode 100644 index 00000000..db698c1c --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomMatchers.kt @@ -0,0 +1,52 @@ +package br.com.fenix.bilingualmangareader.custom + +import android.view.View +import androidx.annotation.DrawableRes +import androidx.appcompat.view.menu.ActionMenuItemView +import androidx.test.espresso.matcher.BoundedMatcher +import com.google.android.material.button.MaterialButton +import org.hamcrest.Description +import org.hamcrest.Matcher + + +object CustomMatchers { + object Button { + fun withActionIconDrawable(@DrawableRes resourceId: Int, ignoreColor: Boolean = false): Matcher { + return object : BoundedMatcher(MaterialButton::class.java) { + override fun describeTo(description: Description) { + description.appendText("has image drawable resource $resourceId") + } + + override fun matchesSafely(buttonView: MaterialButton): Boolean { + return CustomUtils.sameBitmap( + buttonView.context, + buttonView.icon, + resourceId, + buttonView, + ignoreColor + ) + } + } + } + } + + object MenuItem { + fun withActionIconDrawable(@DrawableRes resourceId: Int, ignoreColor: Boolean = false): Matcher { + return object : BoundedMatcher(ActionMenuItemView::class.java) { + override fun describeTo(description: Description) { + description.appendText("has image drawable resource $resourceId") + } + + override fun matchesSafely(actionMenuItemView: ActionMenuItemView): Boolean { + return CustomUtils.sameBitmap( + actionMenuItemView.context, + actionMenuItemView.itemData.icon, + resourceId, + actionMenuItemView, + ignoreColor + ) + } + } + } + } +} diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt new file mode 100644 index 00000000..008e4ced --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt @@ -0,0 +1,63 @@ +package br.com.fenix.bilingualmangareader.custom + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.graphics.drawable.StateListDrawable +import android.view.View + +class CustomUtils { + + companion object CustomUtils { + private fun getBitmapFromDrawable(drawable: Drawable, ignoreColor: Boolean): Bitmap { + val bitmap: Bitmap = Bitmap.createBitmap( + drawable.intrinsicWidth, + drawable.intrinsicHeight, Bitmap.Config.ARGB_8888 + ) + val canvas = Canvas(bitmap) + drawable.setBounds(0, 0, canvas.width, canvas.height) + + if (ignoreColor) + drawable.setTint(Color.WHITE) + + drawable.draw(canvas) + return bitmap + } + + fun sameBitmap( + context: Context, + drawable: Drawable?, + resourceId: Int, + view: View, + ignoreColor: Boolean + ): Boolean { + var drawable = drawable + val otherDrawable: Drawable? = context.resources.getDrawable(resourceId) + if (drawable == null || otherDrawable == null) { + return false + } + + if (drawable is StateListDrawable) { + val getStateDrawableIndex = + StateListDrawable::class.java.getMethod( + "getStateDrawableIndex", + IntArray::class.java + ) + val getStateDrawable = + StateListDrawable::class.java.getMethod( + "getStateDrawable", + Int::class.javaPrimitiveType + ) + val index = getStateDrawableIndex.invoke(drawable, view.drawableState) + drawable = getStateDrawable.invoke(drawable, index) as Drawable + } + + val bitmap = getBitmapFromDrawable(drawable, ignoreColor) + val otherBitmap = getBitmapFromDrawable(otherDrawable, ignoreColor) + + return bitmap.sameAs(otherBitmap) + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/utils/TestUtils.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/utils/TestUtils.kt new file mode 100644 index 00000000..2bd22966 --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/utils/TestUtils.kt @@ -0,0 +1,114 @@ +package br.com.fenix.bilingualmangareader.utils + +import android.content.Context +import android.graphics.BitmapFactory +import br.com.fenix.bilingualmangareader.R +import br.com.fenix.bilingualmangareader.model.entity.Manga +import br.com.fenix.bilingualmangareader.service.controller.ImageCoverController +import br.com.fenix.bilingualmangareader.service.parses.ParseFactory +import br.com.fenix.bilingualmangareader.service.parses.RarParse +import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts +import br.com.fenix.bilingualmangareader.util.helpers.Util +import java.io.File +import java.time.LocalDateTime + +class TestUtils { + + companion object TestUtils { + + private val TEST_FILE_PATH = "storage/emulated/0/Manga/Manga of test.cbr" + + private fun getCoverMipmap(index: Int = 0): Int { + return if (index > 5 || index < 0) + getCoverMipmap((0..5).random()) + else when (index) { + 1 -> R.mipmap.book_cover_1 + 2 -> R.mipmap.book_cover_2 + 3 -> R.mipmap.book_cover_3 + 4 -> R.mipmap.book_cover_4 + 5 -> R.mipmap.book_cover_5 + else -> R.mipmap.book_cover_1 + } + } + + fun generateCovers(context: Context, mangas: ArrayList) { + for ((index, manga) in mangas.withIndex()) + generateCovers(context, manga, index) + } + + fun generateCovers(context: Context, manga: Manga, index: Int = 0) { + val minMap = getCoverMipmap(index) + val cover = BitmapFactory.decodeResource(context.resources, minMap) + ImageCoverController.instance.saveCoverToCache(context, manga, cover) + } + + fun getManga(context: Context, filePath: String = ""): Manga { + val mangaPath = filePath.ifEmpty { TEST_FILE_PATH } + val manga = Manga( + 1, + Util.getNameFromPath(mangaPath), + "", + mangaPath, + Util.getFolderFromPath(mangaPath), + Util.getNameWithoutExtensionFromPath(mangaPath), + Util.getExtensionFromPath(mangaPath), + 10, + 5, + (1..2).random() > 1, + LocalDateTime.parse("2022-06-28T14:15:50.63"), + LocalDateTime.now(), + (1..5).random() > 2 + ) + + if (filePath.isNotEmpty()) { + val parse = ParseFactory.create(filePath) ?: return manga + try { + if (parse is RarParse) { + val folder = GeneralConsts.CACHE_FOLDER.LINKED + '/' + Util.normalizeNameCache(manga.name) + val cacheDir = File(GeneralConsts.getCacheDir(context), folder) + (parse as RarParse?)!!.setCacheDirectory(cacheDir) + } + + manga.pages = parse.numPages() + ImageCoverController.instance.getCoverFromFile(context, manga.file, parse) + } finally { + Util.destroyParse(parse) + } + } else + generateCovers(context, manga) + + return manga + } + + fun getManga(): Manga { + return Manga( + 1, Util.getNameFromPath(TEST_FILE_PATH), "", TEST_FILE_PATH, Util.getFolderFromPath(TEST_FILE_PATH), + Util.getNameWithoutExtensionFromPath(TEST_FILE_PATH), Util.getExtensionFromPath(TEST_FILE_PATH), 10, 5, + (1..2).random() > 1, LocalDateTime.parse("2022-06-28T14:15:50.63"), LocalDateTime.now(), (1..5).random() > 2 + ) + } + + fun getArrayMangas(context: Context): ArrayList { + val mangas = getArrayMangas() + generateCovers(context, mangas) + return mangas + } + + fun getArrayMangas(): ArrayList { + val array = arrayListOf() + + for (i in 0 until 10) + array.add( + Manga( + i.toLong(), Util.getNameFromPath(TEST_FILE_PATH), "", TEST_FILE_PATH, Util.getFolderFromPath(TEST_FILE_PATH), + Util.getNameWithoutExtensionFromPath(TEST_FILE_PATH), Util.getExtensionFromPath(TEST_FILE_PATH), 125, + (0..100).random(), i in 2..5, LocalDateTime.parse("2022-06-28T14:15:50.63"), LocalDateTime.now(), + i in 4..6 + ) + ) + + return array + } + + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivityTest.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivityTest.kt new file mode 100644 index 00000000..da6ae5e3 --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivityTest.kt @@ -0,0 +1,91 @@ +package br.com.fenix.bilingualmangareader.view.ui.manga_detail + +import android.content.Intent +import android.os.Bundle +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.* +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import br.com.fenix.bilingualmangareader.R +import br.com.fenix.bilingualmangareader.custom.CustomMatchers +import br.com.fenix.bilingualmangareader.model.entity.Manga +import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts +import br.com.fenix.bilingualmangareader.utils.TestUtils +import junit.framework.TestCase.assertTrue +import org.hamcrest.Matchers.not +import org.junit.FixMethodOrder +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(AndroidJUnit4::class) +class MangaDetailActivityTest { + + private var manga: Manga + private var intent: Intent? = null + + init { + intent = Intent(ApplicationProvider.getApplicationContext(), MangaDetailActivity::class.java) + val bundle = Bundle() + manga = TestUtils.getManga(ApplicationProvider.getApplicationContext()) + bundle.putSerializable(GeneralConsts.KEYS.OBJECT.MANGA, manga) + intent?.putExtras(bundle) + } + + + @get:Rule + val activityScenarioRule = ActivityScenarioRule(intent) + + @Test + fun `1_test_manga_detail`() { + val scenario = activityScenarioRule.scenario + + scenario.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.root_frame_manga_detail) + assertTrue(fragment is MangaDetailFragment) + } + + onView(withId(R.id.frame_manga_detail_root)).check(matches(isDisplayed())) + + onView(withId(R.id.manga_detail_title)).check(matches(withText(manga.name))) + + onView(withId(R.id.manga_detail_folder)).check(matches(withText(manga.path))) + + onView(withId(R.id.manga_detail_last_access)).check(matches(not(withText("")))) + + onView(withId(R.id.manga_detail_book_mark)).check(matches(not(withText("")))) + + if (manga.favorite) + onView(withId(R.id.manga_detail_button_favorite)).check( + matches( + CustomMatchers.Button.withActionIconDrawable( + R.drawable.ic_favorite_mark, + true + ) + ) + ) + else + onView(withId(R.id.manga_detail_button_favorite)).check( + matches( + CustomMatchers.Button.withActionIconDrawable( + R.drawable.ic_favorite_unmark, + true + ) + ) + ) + + if (manga.excluded) + onView(withId(R.id.manga_detail_deleted)).check(matches(isDisplayed())) + else + onView(withId(R.id.manga_detail_deleted)).check(matches(not(isDisplayed()))) + + //val waiter = CountDownLatch(1) + //waiter.await(10, TimeUnit.SECONDS) + } + +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt new file mode 100644 index 00000000..7d161741 --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt @@ -0,0 +1,127 @@ +package br.com.fenix.bilingualmangareader.view.ui.pages_link + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.core.net.toUri +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import br.com.fenix.bilingualmangareader.R +import br.com.fenix.bilingualmangareader.model.entity.Manga +import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts +import br.com.fenix.bilingualmangareader.utils.TestUtils +import com.google.android.material.progressindicator.CircularProgressIndicator +import junit.framework.TestCase.assertFalse +import junit.framework.TestCase.assertTrue +import org.junit.FixMethodOrder +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(AndroidJUnit4::class) +class PagesLinkActivityTest { + + // Inform a file test here + private val filePath = "" // "storage/emulated/0/Manga/Manga of test.cbr" + private val manga: Manga = TestUtils.getManga(ApplicationProvider.getApplicationContext(), filePath) + private var intent: Intent? = null + + init { + assertFalse("Not informed comic file, please declare 'filePath' in PagesLinkActivityTest", filePath.isEmpty()) + assertTrue("Comic file informed not found, please verify declared 'filePath' in PagesLinkActivityTest", manga.file.exists()) + + intent = Intent(ApplicationProvider.getApplicationContext(), PagesLinkActivity::class.java) + + val bundle = Bundle() + bundle.putSerializable(GeneralConsts.KEYS.OBJECT.MANGA, manga) + bundle.putInt(GeneralConsts.KEYS.MANGA.PAGE_NUMBER, 0) + intent?.putExtras(bundle) + } + + + @get:Rule + val activityScenarioRule = ActivityScenarioRule(intent) + + private val awaitProcessSeconds = 2L + + @Test + fun `1_test_manga_detail`() { + val waiter = CountDownLatch(1) + val scenario = activityScenarioRule.scenario + + scenario.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.root_frame_pages_link) + assertTrue(fragment is PagesLinkFragment) + } + + var progress: CircularProgressIndicator? = null + + scenario.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.root_frame_pages_link) as PagesLinkFragment + + val resultData = Intent() + resultData.data = filePath.toUri() + fragment.onActivityResult(GeneralConsts.REQUEST.OPEN_PAGE_LINK, Activity.RESULT_OK, resultData) + progress = it.findViewById(R.id.pages_link_loading_progress) + } + + // Await load manga images + if (progress != null) { + var waitTime = 0 + do { + waitTime++ + waiter.await(2, TimeUnit.SECONDS) + } while (progress!!.visibility == View.VISIBLE && waitTime < 5) + } + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_help_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_full_screen_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_full_screen_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_dual_page_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_single_page_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_reorder_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_auto_process_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_refresh_button)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.file_link_delete_button)).perform(click()) + + scenario.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.root_frame_pages_link) as PagesLinkFragment + + val resultData = Intent() + resultData.data = filePath.toUri() + fragment.onActivityResult(GeneralConsts.REQUEST.OPEN_PAGE_LINK, Activity.RESULT_OK, resultData) + } + + // Has a error, view another day + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.pages_link_save_button)).perform(click()) + + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt new file mode 100644 index 00000000..4d3c2362 --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt @@ -0,0 +1,14 @@ +package br.com.fenix.bilingualmangareader.view.ui.reader + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(AndroidJUnit4::class) +class ReaderActivityTest { + +} \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/MainActivity.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/MainActivity.kt index 9ae66a45..c57ea79d 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/MainActivity.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/MainActivity.kt @@ -1,11 +1,9 @@ package br.com.fenix.bilingualmangareader -import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.View -import android.view.WindowManager import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar @@ -13,9 +11,8 @@ import androidx.core.view.GravityCompat import androidx.drawerlayout.widget.DrawerLayout import androidx.fragment.app.FragmentManager import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts -import br.com.fenix.bilingualmangareader.view.components.ComponentsUtil import br.com.fenix.bilingualmangareader.view.ui.configuration.ConfigFragment -import br.com.fenix.bilingualmangareader.view.ui.help.AboutFragment +import br.com.fenix.bilingualmangareader.view.ui.about.AboutFragment import br.com.fenix.bilingualmangareader.view.ui.help.HelpFragment import br.com.fenix.bilingualmangareader.view.ui.history.HistoryFragment import br.com.fenix.bilingualmangareader.view.ui.library.LibraryFragment diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Manga.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Manga.kt index b0cd92f7..5b373d2e 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Manga.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Manga.kt @@ -26,6 +26,20 @@ class Manga(id: Long?, title: String, subTitle: String, path: String, folder: St this.sort = sort } + constructor( + id: Long?, title: String, subTitle: String, + path: String, folder: String, name: String, type: String, + pages: Int, bookMark: Int, favorite: Boolean, + dateCreate: LocalDateTime?, lastAccess: LocalDateTime?, + excluded: Boolean = false + ) : this(id, title, subTitle, path, folder, name, type, pages) { + this.bookMark = bookMark + this.favorite = favorite + this.dateCreate = dateCreate + this.lastAccess = lastAccess + this.excluded = excluded + } + @PrimaryKey(autoGenerate = true) @ColumnInfo(name = DataBaseConsts.MANGA.COLUMNS.ID) var id: Long? = id @@ -92,6 +106,7 @@ class Manga(id: Long?, title: String, subTitle: String, path: String, folder: St other as Manga if (id != other.id) return false + if (path != other.path) return false if (name != other.name) return false if (type != other.type) return false @@ -100,6 +115,7 @@ class Manga(id: Long?, title: String, subTitle: String, path: String, folder: St override fun hashCode(): Int { var result = id?.hashCode() ?: 0 + result = 31 * result + path.hashCode() result = 31 * result + name.hashCode() result = 31 * result + type.hashCode() return result diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/controller/ImageCoverController.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/controller/ImageCoverController.kt index c8fa807a..44987f8d 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/service/controller/ImageCoverController.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/controller/ImageCoverController.kt @@ -91,6 +91,10 @@ class ImageCoverController private constructor() { return null } + fun saveCoverToCache(context: Context, manga: Manga, bitmap: Bitmap) { + saveBitmapToCache(context, generateHash(manga.file), bitmap) + } + fun getCoverFromFile(context: Context, file: File, parse: Parse): Bitmap? { return getCoverFromFile(context, generateHash(file), parse) } @@ -98,7 +102,7 @@ class ImageCoverController private constructor() { private fun generateHash(file: File): String = Util.MD5(file.path + file.name) - private fun getCoverFromFile(context: Context, hash: String, parse: Parse): Bitmap? { + private fun getCoverFromFile(context: Context, hash: String, parse: Parse, isCoverSize: Boolean = true): Bitmap? { var index = 0 for (i in 0..parse.numPages()) { if (Util.isImage(parse.getPagePath(i)!!)) { @@ -108,31 +112,42 @@ class ImageCoverController private constructor() { } var stream: InputStream? = parse.getPage(index) - val options = BitmapFactory.Options() - options.inJustDecodeBounds = true - BitmapFactory.decodeStream(stream, null, options) - options.inSampleSize = Util.calculateInSampleSize( - options, - ReaderConsts.COVER.COVER_THUMBNAIL_WIDTH, - ReaderConsts.COVER.COVER_THUMBNAIL_HEIGHT - ) - - options.inJustDecodeBounds = false - Util.closeInputStream(stream) - stream = parse.getPage(index) - val result = BitmapFactory.decodeStream(stream, null, options) - - return if (result != null) { - saveBitmapToCache(context, hash, result) + val cover: Bitmap? + + if (isCoverSize) { + val option = BitmapFactory.Options() + option.inJustDecodeBounds = true + BitmapFactory.decodeStream(stream, null, option) + option.inSampleSize = Util.calculateInSampleSize( + option, + ReaderConsts.COVER.COVER_THUMBNAIL_WIDTH, + ReaderConsts.COVER.COVER_THUMBNAIL_HEIGHT + ) + option.inJustDecodeBounds = false + Util.closeInputStream(stream) - result - } else - null + stream = parse.getPage(index) + cover = BitmapFactory.decodeStream(stream, null, option) + if (cover != null) + saveBitmapToCache(context, hash, cover) + + Util.closeInputStream(stream) + } else { + stream = parse.getPage(index) + cover = BitmapFactory.decodeStream(stream) + Util.closeInputStream(stream) + } + + return cover } - private fun getMangaCover(context: Context, manga: Manga): Bitmap? { + private fun getMangaCover(context: Context, manga: Manga, isCoverSize: Boolean): Bitmap? { val hash = generateHash(manga.file) - var image = retrieveBitmapFromCache(context, hash) + var image: Bitmap? = null + + if (isCoverSize) + image = retrieveBitmapFromCache(context, hash) + if (image == null) { val parse = ParseFactory.create(manga.file) ?: return image try { @@ -142,7 +157,7 @@ class ImageCoverController private constructor() { (parse as RarParse?)!!.setCacheDirectory(cacheDir) } - image = getCoverFromFile(context, hash, parse) + image = getCoverFromFile(context, hash, parse, isCoverSize) } finally { Util.destroyParse(parse) } @@ -154,13 +169,14 @@ class ImageCoverController private constructor() { fun setImageCoverAsync( context: Context, manga: Manga, - imageView: ImageView + imageView: ImageView, + isCoverSize: Boolean = true ) { CoroutineScope(Dispatchers.IO).launch { try { var image: Bitmap? = null val deferred = async { - image = getMangaCover(context, manga) + image = getMangaCover(context, manga, isCoverSize) } deferred.await() withContext(Dispatchers.Main) { @@ -174,7 +190,34 @@ class ImageCoverController private constructor() { mLOGGER.error("Memory full, cleaning", m) } } + } + fun setImageCoverAsync( + context: Context, + manga: Manga, + imagesView: ArrayList, + isCoverSize: Boolean = true + ) { + CoroutineScope(Dispatchers.IO).launch { + try { + var image: Bitmap? = null + val deferred = async { + image = getMangaCover(context, manga, isCoverSize) + } + deferred.await() + withContext(Dispatchers.Main) { + if (image != null) { + for (imageView in imagesView) + imageView.setImageBitmap(image) + } + } + } catch (e: Exception) { + mLOGGER.error("Error to load image array async", e) + } catch (m: OutOfMemoryError) { + System.gc() + mLOGGER.error("Memory full, cleaning", m) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/util/helpers/Util.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/util/helpers/Util.kt index fc3f1402..549bb8d7 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/util/helpers/Util.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/util/helpers/Util.kt @@ -220,6 +220,29 @@ class Util { path } + fun getNameWithoutExtensionFromPath(path: String): String { + var name = if (path.contains('/')) + path.substringAfterLast("/") + else if (path.contains('\\')) + path.substringAfterLast('\\') + else + path + + name = if (name.contains('.')) + name.substringBefore(".") + else + name + + return name + } + + fun getExtensionFromPath(path: String): String { + return if (path.contains('.')) + path.substringAfterLast(".") + else + path + } + fun normalizeNameCache(name: String): String { val normalize = if (name.contains("-")) name.substringBefore("-") diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/about/AboutFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/about/AboutFragment.kt index ab96a420..17196b26 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/about/AboutFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/about/AboutFragment.kt @@ -1,4 +1,4 @@ -package br.com.fenix.bilingualmangareader.view.ui.help +package br.com.fenix.bilingualmangareader.view.ui.about import android.content.ActivityNotFoundException import android.content.Intent diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt index 040fa2b3..ba7249eb 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt @@ -1,23 +1,16 @@ package br.com.fenix.bilingualmangareader.view.ui.configuration -import android.Manifest.permission.READ_EXTERNAL_STORAGE -import android.Manifest.permission.WRITE_EXTERNAL_STORAGE import android.app.Activity.RESULT_OK import android.content.Intent import android.content.pm.PackageManager -import android.os.Build -import android.os.Build.VERSION.SDK_INT import android.os.Bundle -import android.os.Environment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.AutoCompleteTextView -import android.widget.Toast import androidx.appcompat.app.AlertDialog -import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import br.com.fenix.bilingualmangareader.R import br.com.fenix.bilingualmangareader.model.enums.Languages diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt index c9b5e6df..ff59c9e5 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt @@ -85,9 +85,9 @@ class LibraryFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { inflater.inflate(R.menu.main_menu, menu) super.onCreateOptionsMenu(menu, inflater) - miGridType = menu.findItem(R.id.grid_type) - miGridOrder = menu.findItem(R.id.list_order) - miSearch = menu.findItem(R.id.search) + miGridType = menu.findItem(R.id.menu_library_grid_type) + miGridOrder = menu.findItem(R.id.menu_library_list_order) + miSearch = menu.findItem(R.id.menu_library_search) searchView = miSearch.actionView as SearchView searchView.imeOptions = EditorInfo.IME_ACTION_DONE searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { @@ -174,8 +174,8 @@ class LibraryFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { override fun onOptionsItemSelected(menuItem: MenuItem): Boolean { when (menuItem.itemId) { - R.id.grid_type -> onChangeLayout() - R.id.list_order -> onChangeSort() + R.id.menu_library_grid_type -> onChangeLayout() + R.id.menu_library_list_order -> onChangeSort() } return super.onOptionsItemSelected(menuItem) } @@ -268,7 +268,7 @@ class LibraryFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { Order.LastAccess to getString(R.string.config_option_order_access), Order.Favorite to getString(R.string.config_option_order_favorite) ) - mRoot = root.findViewById(R.id.library_root) + mRoot = root.findViewById(R.id.frame_library_root) mRecycleView = root.findViewById(R.id.library_recycler_view) mRefreshLayout = root.findViewById(R.id.library_refresh) mScrollUp = root.findViewById(R.id.library_scroll_up) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivity.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivity.kt index 7cfc6962..ff47c3ec 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivity.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailActivity.kt @@ -8,7 +8,6 @@ import androidx.appcompat.widget.Toolbar import br.com.fenix.bilingualmangareader.R import br.com.fenix.bilingualmangareader.model.entity.Manga import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts -import br.com.fenix.bilingualmangareader.view.components.ComponentsUtil class MangaDetailActivity : AppCompatActivity() { diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt index efab592d..eb261e29 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt @@ -103,8 +103,7 @@ class MangaDetailFragment(private var mManga: Manga?) : Fragment() { private fun observer() { mViewModel.manga.observe(viewLifecycleOwner) { if (it != null) { - ImageCoverController.instance.setImageCoverAsync(requireContext(), it, mBackgroundImage) - ImageCoverController.instance.setImageCoverAsync(requireContext(), it, mImage) + ImageCoverController.instance.setImageCoverAsync(requireContext(), it, arrayListOf(mBackgroundImage, mImage), false) mTitle.text = it.name mFolder.text = it.path mBookMark.text = "${it.bookMark} / ${it.pages}" diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivity.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivity.kt index 512ca8c1..ca1c04ee 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivity.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivity.kt @@ -7,7 +7,6 @@ import androidx.appcompat.widget.Toolbar import br.com.fenix.bilingualmangareader.R import br.com.fenix.bilingualmangareader.model.entity.Manga import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts -import br.com.fenix.bilingualmangareader.view.components.ComponentsUtil class PagesLinkActivity : AppCompatActivity() { diff --git a/app/src/main/res/layout-land/fragment_pages_link.xml b/app/src/main/res/layout-land/fragment_pages_link.xml index 9ebf7c3b..6a3db8aa 100644 --- a/app/src/main/res/layout-land/fragment_pages_link.xml +++ b/app/src/main/res/layout-land/fragment_pages_link.xml @@ -2,6 +2,7 @@ - Date: Wed, 29 Jun 2022 00:32:16 -0300 Subject: [PATCH 03/28] =?UTF-8?q?Corrigido=20erro=20de=20ordena=C3=A7?= =?UTF-8?q?=C3=A3o=20do=20page=20link,=20tanto=20na=20dupla=20p=C3=A1gina?= =?UTF-8?q?=20quanto=20na=20simples.=20Ajustado=20tamb=C3=A9m=20o=20reproc?= =?UTF-8?q?essamento=20da=20ordem=20para=20gerar=20uma=20nova=20lista=20or?= =?UTF-8?q?denada.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/entity/PageLink.kt | 5 + .../view/ui/pages_link/PagesLinkViewModel.kt | 165 +++++++++++++----- .../view/ui/reader/ReaderActivity.kt | 1 - 3 files changed, 130 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt index 712ca326..3c6370b9 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/PageLink.kt @@ -174,6 +174,11 @@ class PageLink( this.isFileLeftDualPage = isFileLeftDualPage } + constructor(pageLink: PageLink) : this( + pageLink.id, pageLink.mangaPage, pageLink.mangaPages, pageLink.mangaPageName, + pageLink.mangaPagePath, pageLink.isMangaDualPage, pageLink.imageMangaPage + ) + @PrimaryKey(autoGenerate = true) @ColumnInfo(name = DataBaseConsts.PAGESLINK.COLUMNS.ID) var id: Long? = id diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt index 280be233..2972cb17 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkViewModel.kt @@ -11,6 +11,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import br.com.fenix.bilingualmangareader.model.entity.FileLink import br.com.fenix.bilingualmangareader.model.entity.Manga +import br.com.fenix.bilingualmangareader.model.entity.Page import br.com.fenix.bilingualmangareader.model.entity.PageLink import br.com.fenix.bilingualmangareader.model.enums.Languages import br.com.fenix.bilingualmangareader.model.enums.LoadFile @@ -260,6 +261,9 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio fileLink.parseManga = mFileLink.value!!.parseManga for ((index, page) in fileLink.pagesLink!!.withIndex()) { + if (index >= mPagesLink.value!!.size) + break + page.imageMangaPage = mPagesLink.value!![index].imageMangaPage if (page.fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { @@ -771,8 +775,6 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio if (page.dualImage || (isUseDualPageCalculate && page.isFileLeftDualPage)) continue - println("" + index + "||" + padding) - if ((index + padding) >= pagesLink.size) break @@ -809,6 +811,11 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio next.clearRightFileLink() } else { padding++ + if ((index + padding) >= pagesLink.size) { + padding-- + continue + } + next = pagesLink[index + padding] if (next.fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY && !next.dualImage && !next.isFileLeftDualPage) { page.addRightFromLeftFileLinkImage(next) @@ -835,10 +842,15 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio indexChanges.addAll(arrayOf(index, index + padding)) if (next.fileRightLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { - page.addRightFromLeftFileLinkImage(next) + page.addRightFileLinkImage(next) next.clearRightFileLink() } else { padding++ + if ((index + padding) >= pagesLink.size) { + padding-- + continue + } + next = pagesLink[index + padding] if (!next.dualImage && next.fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { page.addRightFromLeftFileLinkImage(next) @@ -848,14 +860,50 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio padding-- } } else { - page.addRightFileLinkImage(next) + page.addRightFromLeftFileLinkImage(next) next.clearLeftFileLink() indexChanges.addAll(arrayOf(index, index + padding)) } } } + } + + if (mPagesNotLinked.value!!.isNotEmpty()) { + val pagesNotLinked = mPagesNotLinked.value!!.sortedBy { it.fileLinkPage }.toMutableList() + + for (page in pagesLink) { + if (pagesNotLinked.isEmpty()) + break + + if (page.dualImage || (isUseDualPageCalculate && page.isFileRightDualPage)) + continue + + if (page.fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) + page.addRightFromLeftFileLinkImage(pagesNotLinked.removeAt(0)) + else if (isUseDualPageCalculate) { + val notLinked = pagesNotLinked.removeAt(0) + page.addLeftFileLinkImage(notLinked) + + if (notLinked.isFileLeftDualPage) + continue + + if (pagesNotLinked.isEmpty()) + break + page.addRightFromLeftFileLinkImage(pagesNotLinked.removeAt(0)) + } else { + page.addLeftFileLinkImage(pagesNotLinked.removeAt(0)) + if (pagesNotLinked.isEmpty()) + break + + page.addRightFromLeftFileLinkImage(pagesNotLinked.removeAt(0)) + } + } + + mPagesNotLinked.value!!.clear() + if (pagesNotLinked.isNotEmpty()) + mPagesNotLinked.value!!.addAll(pagesNotLinked) - println("Right: image " + page.fileRightLinkPageName) + notifyMessages(Pages.NOT_LINKED, PageLinkConsts.MESSAGES.MESSAGE_PAGES_LINK_ITEM_CHANGE) } for (index in indexChanges) @@ -877,29 +925,67 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio val indexChanges = mutableSetOf() val pagesLink = mPagesLink.value!! var amount = 0 - pagesLink.forEach { if (it.dualImage) amount += 1 } + pagesLink.forEach { if (it.dualImage) amount += 1 } + var amountNotLink = (amount * 2) - pagesLink.size - for (i in pagesLink.size - 1 downTo (pagesLink.size - 1) - amount) - addNotLinked(pagesLink[i]) + if (amountNotLink > 0) { + for (i in (pagesLink.size - 1) downTo 0) { + val item = pagesLink[i] + if (item.fileLinkPage == PageLinkConsts.VALUES.PAGE_EMPTY) + continue - if (isNotify) - notifyMessages(Pages.NOT_LINKED, PageLinkConsts.MESSAGES.MESSAGE_PAGES_LINK_ITEM_CHANGE) + val page = pagesLink[i] + if (item.dualImage) { + addNotLinked(page) + amountNotLink -= 2 + page.clearFileLink() + } else if (item.fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { + addNotLinked(page) + amountNotLink-- + page.clearLeftFileLink() + } - var process = amount - for (i in pagesLink.size - 1 downTo 0) { - val page = pagesLink[i - process] - if (page.dualImage) { - pagesLink[i].addLeftFileLinkImage(page) - page.clearRightFileLink() - process -= 1 - } else - pagesLink[i].addLeftFileLinkImage(page) - - indexChanges.addAll(arrayOf(i, i - process)) - if (process <= 0) + if (amountNotLink < 1) + break + } + + mPagesNotLinked.value!!.sortBy { it.fileLinkPage } + + if (isNotify) + notifyMessages(Pages.NOT_LINKED, PageLinkConsts.MESSAGES.MESSAGE_PAGES_LINK_ITEM_CHANGE) + } + + var padding = 0 + for (i in (pagesLink.size - 1) downTo 0) { + if (pagesLink[i].fileLinkPage != PageLinkConsts.VALUES.PAGE_EMPTY) { + padding = i +1 break + } + } + + val pagesLinkTemp = mutableListOf() + + for (i in pagesLink.size - 1 downTo 0) { + val newPage = PageLink(pagesLink[i]) + pagesLinkTemp.add(newPage) + + if (i - padding >= 0) { + val page = pagesLink[i - padding] + + if (page.dualImage) { + newPage.addLeftFromRightFileLinkImage(page) + page.clearRightFileLink() + padding-- + } else + newPage.addLeftFileLinkImage(page) + } + + indexChanges.addAll(arrayOf(i, i - padding)) } + pagesLinkTemp.sortBy { it.mangaPage } + mPagesLink.value = ArrayList(pagesLinkTemp) + if (isNotify) { for (index in indexChanges) notifyMessages(Pages.LINKED, PageLinkConsts.MESSAGES.MESSAGE_PAGES_LINK_ITEM_CHANGE, index) @@ -991,8 +1077,8 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio val pagesNotLink = mPagesNotLinked.value!! val pagesLink = mPagesLink.value!! - val pagesLinkTemp = pagesLink.toMutableList() - val pagesNotLinkTemp = ArrayList() + val pagesLinkTemp = mutableListOf() + val pagesNotLinkTemp = arrayListOf() var maxNumPage = 0 for (page in pagesLink) { @@ -1008,29 +1094,25 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio maxNumPage = page.fileLinkPage } - pagesLinkTemp.removeAll { it.mangaPage == PageLinkConsts.VALUES.PAGE_EMPTY } - - for (page in pagesLinkTemp) { - if (page.mangaPage == PageLinkConsts.VALUES.PAGE_EMPTY) { - page.clearFileLink() + for (page in pagesLink) { + if (page.mangaPage == PageLinkConsts.VALUES.PAGE_EMPTY) continue - } if (page.mangaPage > maxNumPage) - page.clearFileLink() + break else { - val pageLink = pagesLink.find { it.fileLinkPage == page.mangaPage || it.fileRightLinkPage == page.mangaPage } + val pageLink = PageLink(page) + pagesLinkTemp.add(pageLink) + + val findPageLink = pagesLink.find { it.fileLinkPage == page.mangaPage || it.fileRightLinkPage == page.mangaPage } ?: pagesNotLink.find { it.fileLinkPage == page.mangaPage } - if (pageLink != null) { - if (pageLink.fileLinkPage == page.mangaPage) - page.addLeftFileLinkImage(pageLink) + if (findPageLink != null) { + if (pageLink.fileRightLinkPage == page.mangaPage) + pageLink.addLeftFromRightFileLinkImage(findPageLink) else - page.addLeftFileLinkImage(pageLink) - - page.clearRightFileLink() - } else - page.clearFileLink() + pageLink.addLeftFileLinkImage(findPageLink) + } } } @@ -1060,6 +1142,9 @@ class PagesLinkViewModel(application: Application) : AndroidViewModel(applicatio pagesLink.clear() pagesNotLink.clear() + pagesLinkTemp.sortBy { it.mangaPage } + pagesNotLinkTemp.sortBy { it.fileLinkPage } + mPagesLink.value = ArrayList(pagesLinkTemp) mPagesNotLinked.value = pagesNotLinkTemp diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt index f2142633..134fb354 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt @@ -276,7 +276,6 @@ class ReaderActivity : AppCompatActivity(), OcrProcess { } } - //ComponentsUtil.setSystemUITransparency(window) } private fun switchManga(isNext: Boolean = true) { From 31e32863c4afc596aea504f0b641cd605983fb34 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Wed, 29 Jun 2022 00:32:39 -0300 Subject: [PATCH 04/28] =?UTF-8?q?Criado=20o=20teste=20da=20tela=20page=20l?= =?UTF-8?q?ink,=20e=20adicionado=20as=20fun=C3=A7=C3=B5es=20padr=C3=B5es?= =?UTF-8?q?=20de=20teste=20do=20reader.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../custom/CustomTypes.kt | 12 ++ .../custom/CustomUtils.kt | 3 + .../ui/pages_link/PagesLinkActivityTest.kt | 5 +- .../view/ui/reader/ReaderActivityTest.kt | 108 +++++++++++++++++- 4 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomTypes.kt diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomTypes.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomTypes.kt new file mode 100644 index 00000000..5ee138cb --- /dev/null +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomTypes.kt @@ -0,0 +1,12 @@ +package br.com.fenix.bilingualmangareader.custom + +import androidx.annotation.IdRes + +class CustomTypes { + + enum class AlertDialogButton(@IdRes val resId: Int) { + POSITIVE(android.R.id.button1), + NEGATIVE(android.R.id.button2), + NEUTRAL(android.R.id.button3) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt index 008e4ced..6b8832c1 100644 --- a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/custom/CustomUtils.kt @@ -7,6 +7,7 @@ import android.graphics.Color import android.graphics.drawable.Drawable import android.graphics.drawable.StateListDrawable import android.view.View +import androidx.annotation.IdRes class CustomUtils { @@ -59,5 +60,7 @@ class CustomUtils { return bitmap.sameAs(otherBitmap) } + } + } \ No newline at end of file diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt index 7d161741..fdbf69bb 100644 --- a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkActivityTest.kt @@ -33,6 +33,7 @@ class PagesLinkActivityTest { // Inform a file test here private val filePath = "" // "storage/emulated/0/Manga/Manga of test.cbr" + private val filePathLink = filePath private val manga: Manga = TestUtils.getManga(ApplicationProvider.getApplicationContext(), filePath) private var intent: Intent? = null @@ -70,7 +71,7 @@ class PagesLinkActivityTest { val fragment = it.supportFragmentManager.findFragmentById(R.id.root_frame_pages_link) as PagesLinkFragment val resultData = Intent() - resultData.data = filePath.toUri() + resultData.data = filePathLink.toUri() fragment.onActivityResult(GeneralConsts.REQUEST.OPEN_PAGE_LINK, Activity.RESULT_OK, resultData) progress = it.findViewById(R.id.pages_link_loading_progress) } @@ -115,7 +116,7 @@ class PagesLinkActivityTest { val fragment = it.supportFragmentManager.findFragmentById(R.id.root_frame_pages_link) as PagesLinkFragment val resultData = Intent() - resultData.data = filePath.toUri() + resultData.data = filePathLink.toUri() fragment.onActivityResult(GeneralConsts.REQUEST.OPEN_PAGE_LINK, Activity.RESULT_OK, resultData) } diff --git a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt index 4d3c2362..c341a8bc 100644 --- a/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt +++ b/app/src/androidTest/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivityTest.kt @@ -1,14 +1,120 @@ package br.com.fenix.bilingualmangareader.view.ui.reader +import android.content.Intent +import android.os.Bundle +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import br.com.fenix.bilingualmangareader.R +import br.com.fenix.bilingualmangareader.custom.CustomTypes +import br.com.fenix.bilingualmangareader.model.entity.Manga +import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts +import br.com.fenix.bilingualmangareader.utils.TestUtils +import junit.framework.TestCase.assertFalse +import junit.framework.TestCase.assertTrue import org.junit.FixMethodOrder +import org.junit.Rule +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit @FixMethodOrder(MethodSorters.NAME_ASCENDING) @RunWith(AndroidJUnit4::class) class ReaderActivityTest { + // Inform a file test here + private val filePath = "/storage/emulated/0/Manga/jp/Aho Girl - Volume 01 (Jap).cbr" // "storage/emulated/0/Manga/Manga of test.cbr" + private val manga: Manga = TestUtils.getManga(ApplicationProvider.getApplicationContext(), filePath) + private var intent: Intent? = null + + init { + assertFalse("Not informed comic file, please declare 'filePath' in ReaderActivityTest", filePath.isEmpty()) + assertTrue("Comic file informed not found, please verify declared 'filePath' in ReaderActivityTest", manga.file.exists()) + + intent = Intent(ApplicationProvider.getApplicationContext(), ReaderActivity::class.java) + + val bundle = Bundle() + bundle.putSerializable(GeneralConsts.KEYS.OBJECT.MANGA, manga) + bundle.putString(GeneralConsts.KEYS.MANGA.NAME, manga.title) + bundle.putInt(GeneralConsts.KEYS.MANGA.PAGE_NUMBER, 0) + bundle.putInt(GeneralConsts.KEYS.MANGA.MARK, 0) + intent?.putExtras(bundle) + } + + + @get:Rule + val activityScenarioRule = ActivityScenarioRule(intent) + + private val awaitProcessSeconds = 2L + + @Test + fun `1_test_manga_detail`() { + val waiter = CountDownLatch(1) + val scenario = activityScenarioRule.scenario + + scenario.onActivity { + val fragment = it.supportFragmentManager.findFragmentById(R.id.root_frame_reader) + assertTrue(fragment is ReaderFragment) + } + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.btn_popup_open_floating)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.btn_menu_page_linked)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.btn_popup_color)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.btn_popup_subtitle)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.btn_menu_ocr)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.btn_screen_rotate)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.nav_next_file)).perform(click()) + + onView(withId(CustomTypes.AlertDialogButton.POSITIVE.resId)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.root_frame_reader)).perform(click()) + + waiter.await(awaitProcessSeconds, TimeUnit.SECONDS) + onView(withId(R.id.nav_previous_file)).perform(click()) + + onView(withId(CustomTypes.AlertDialogButton.POSITIVE.resId)).perform(click()) + + } + } \ No newline at end of file From 2a345b46ffdf68a02b36a4e0a3342fbee8910a7f Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Wed, 29 Jun 2022 00:34:12 -0300 Subject: [PATCH 05/28] =?UTF-8?q?Atualizado=20a=20vers=C3=A3o.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7352c494..ed57e9d9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "br.com.fenix.bilingualmangareader" minSdk 26 targetSdk 31 - versionCode 11 - versionName "2.11" + versionCode 12 + versionName "2.12" archivesBaseName = "BilingualManga_" + versionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" From 8229bd3198db40a996061c7149a5bbdb5d31a3b6 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Wed, 29 Jun 2022 08:45:48 -0300 Subject: [PATCH 06/28] Adding update last change on refresh. --- .../service/repository/DataBaseDAO.kt | 3 ++ .../service/repository/MangaRepository.kt | 9 ++++ .../view/ui/library/LibraryFragment.kt | 8 ++-- .../view/ui/library/LibraryViewModel.kt | 41 +++++++++++++------ 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt index d9b1de7d..30ba4769 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt @@ -29,6 +29,9 @@ abstract class MangaDAO : DataBaseDAO { @Query("SELECT * FROM " + DataBaseConsts.MANGA.TABLE_NAME + " WHERE " + DataBaseConsts.MANGA.COLUMNS.EXCLUDED + " = 0 ") abstract fun list(): List + @Query("SELECT * FROM " + DataBaseConsts.MANGA.TABLE_NAME + " WHERE " + DataBaseConsts.MANGA.COLUMNS.EXCLUDED + " = 0 AND " + DataBaseConsts.MANGA.COLUMNS.LAST_ACCESS + " >= datetime('now','-1 days')") + abstract fun listRecentChange(): List + @Query( "SELECT * FROM ( " + " SELECT ${DataBaseConsts.MANGA.COLUMNS.ID}, ${DataBaseConsts.MANGA.COLUMNS.TITLE}, ${DataBaseConsts.MANGA.COLUMNS.SUB_TITLE}, ${DataBaseConsts.MANGA.COLUMNS.FILE_PATH}, " + diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/MangaRepository.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/MangaRepository.kt index 7094ce2f..7a63c032 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/MangaRepository.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/MangaRepository.kt @@ -45,6 +45,15 @@ class MangaRepository(context: Context) { } } + fun listRecentChange(): List? { + return try { + mDataBase.listRecentChange() + } catch (e: Exception) { + mLOGGER.error("Error when list Manga: " + e.message, e) + null + } + } + fun listDeleted(): List? { return try { mDataBase.listDeleted() diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt index ff59c9e5..2f12ccc4 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryFragment.kt @@ -119,11 +119,10 @@ class LibraryFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { if (Scanner.getInstance(requireContext()).isRunning()) setIsRefreshing(true) - mViewModel.update() - mRecycleView - if (mViewModel.isEmpty()) onRefresh() + else + mViewModel.updateList { if (it) sortList(mViewModel.listMangas.value!!) } } override fun onStop() { @@ -483,8 +482,7 @@ class LibraryFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } override fun onRefresh() { - if (mViewModel.isEmpty()) - mViewModel.list { } + mViewModel.updateList { if (it) sortList(mViewModel.listMangas.value!!) } if (mHandler.hasCallbacks(mDismissUpButton)) mHandler.removeCallbacks(mDismissUpButton) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryViewModel.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryViewModel.kt index a71c26e5..f566baff 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryViewModel.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/library/LibraryViewModel.kt @@ -49,19 +49,6 @@ class LibraryViewModel(application: Application) : AndroidViewModel(application) mListMangas.value!!.removeAt(position) } - fun update() { - if (mListMangas.value != null) { - for (manga in mListMangas.value!!) { - val item = mMangaRepository.get(manga.id!!) - if (item != null) { - manga.bookMark = item.bookMark - manga.favorite = item.favorite - manga.lastAccess = item.lastAccess - } - } - } - } - fun update(list: List) { if (list.isNotEmpty()) { for (manga in list) { @@ -126,6 +113,34 @@ class LibraryViewModel(application: Application) : AndroidViewModel(application) return index } + fun updateList(refreshComplete: (Boolean) -> (Unit)) { + var change = false + if (mListMangas.value != null && mListMangas.value!!.isNotEmpty()) { + val list = mMangaRepository.listRecentChange() + if (list != null && list.isNotEmpty()) { + change = true + for (manga in list) { + if (mListMangas.value!!.contains(manga)) { + val index = mListMangas.value!!.indexOf(manga) + mListMangas.value!![index].bookMark = manga.bookMark + mListMangas.value!![index].favorite = manga.favorite + mListMangas.value!![index].lastAccess = manga.lastAccess + } else + mListMangas.value!!.add(manga) + } + } + } else { + val list = mMangaRepository.list() + if (list != null) + mListMangas.value = list.toMutableList() + else + mListMangas.value = mutableListOf() + change = true + } + + refreshComplete(change) + } + fun list(refreshComplete: (Boolean) -> (Unit)) { val list = mMangaRepository.list() if (list != null) { From 69232d6962e15e49ae2983c504733bf278ba3390 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Wed, 29 Jun 2022 10:45:58 -0300 Subject: [PATCH 07/28] =?UTF-8?q?Adicionado=20anima=C3=A7=C3=A3o=20na=20ex?= =?UTF-8?q?panss=C3=A3o=20dos=20bot=C3=B5es=20na=20tela=20de=20pages=20lin?= =?UTF-8?q?k.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/repository/DataBaseDAO.kt | 2 +- .../view/components/ComponentsUtil.kt | 33 +++++++++++++++++++ .../view/ui/pages_link/PagesLinkFragment.kt | 24 +++++--------- .../layout-sw600dp/fragment_pages_link.xml | 2 +- .../main/res/layout/fragment_pages_link.xml | 2 +- 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt index 30ba4769..91ac38ef 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/repository/DataBaseDAO.kt @@ -29,7 +29,7 @@ abstract class MangaDAO : DataBaseDAO { @Query("SELECT * FROM " + DataBaseConsts.MANGA.TABLE_NAME + " WHERE " + DataBaseConsts.MANGA.COLUMNS.EXCLUDED + " = 0 ") abstract fun list(): List - @Query("SELECT * FROM " + DataBaseConsts.MANGA.TABLE_NAME + " WHERE " + DataBaseConsts.MANGA.COLUMNS.EXCLUDED + " = 0 AND " + DataBaseConsts.MANGA.COLUMNS.LAST_ACCESS + " >= datetime('now','-1 days')") + @Query("SELECT * FROM " + DataBaseConsts.MANGA.TABLE_NAME + " WHERE " + DataBaseConsts.MANGA.COLUMNS.EXCLUDED + " = 0 AND " + DataBaseConsts.MANGA.COLUMNS.LAST_ACCESS + " >= datetime('now','-1 day')") abstract fun listRecentChange(): List @Query( diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt index c8fcb8e4..75188c09 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt @@ -5,6 +5,10 @@ import android.animation.AnimatorListenerAdapter import android.content.Context import android.provider.Settings import android.view.View +import android.view.ViewGroup +import android.view.animation.Animation +import android.view.animation.Transformation +import androidx.constraintlayout.widget.ConstraintLayout class ComponentsUtil { @@ -61,5 +65,34 @@ class ComponentsUtil { } } + fun changeWidthAnimateSize(view: View, finalLayout: ConstraintLayout.LayoutParams, isExpanded:Boolean? = null) { + val isInitialExpanded = isExpanded ?: (view.width >= finalLayout.width) + view.layoutParams = ConstraintLayout.LayoutParams(view.layoutParams as ConstraintLayout.LayoutParams) + + val finalWidth = finalLayout.width + val initialWidth = if (isInitialExpanded) view.width - finalLayout.width else view.width + + val animation: Animation = object : Animation() { + override fun applyTransformation(interpolatedTime: Float, t: Transformation?) { + if (interpolatedTime >= 1f) + view.layoutParams = finalLayout + else { + view.layoutParams.width = if (isInitialExpanded) + finalWidth + (initialWidth - (initialWidth * interpolatedTime).toInt()) + else + initialWidth + (finalWidth * interpolatedTime).toInt() + } + view.requestLayout() + } + + override fun willChangeBounds(): Boolean { + return true + } + } + + animation.duration = duration/2 + view.startAnimation(animation) + } + } } \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt index c28f7e28..dd97d5ef 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt @@ -13,7 +13,6 @@ import android.view.DragEvent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams import android.widget.* import androidx.appcompat.app.AlertDialog import androidx.constraintlayout.widget.ConstraintLayout @@ -90,7 +89,7 @@ class PagesLinkFragment : Fragment() { private val mDismissUpButton = Runnable { mScrollUp.hide() } private val mDismissDownButton = Runnable { mScrollDown.hide() } private val mReduceSizeGroupButton = Runnable { - mButtonsGroup.layoutParams = mButtonsGroupSize + ComponentsUtil.changeWidthAnimateSize(mButtonsGroup, mCollapseButtonsGroupSize, true) changColorButton(requireContext().getColor(R.color.file_link_buttons)) } @@ -99,7 +98,8 @@ class PagesLinkFragment : Fragment() { private var mInDrag: Boolean = false private var mIsTabletOrLandscape: Boolean = false private var mPageSelected: Int = 0 - private lateinit var mButtonsGroupSize: LayoutParams + private lateinit var mCollapseButtonsGroupSize: ConstraintLayout.LayoutParams + private lateinit var mExpandedButtonsGroupSize: ConstraintLayout.LayoutParams override fun onCreateView( inflater: LayoutInflater, @@ -138,7 +138,10 @@ class PagesLinkFragment : Fragment() { mMangaName = root.findViewById(R.id.pages_link_name_manga) mToolbar = requireActivity().findViewById(R.id.toolbar_manga_pages_link) - mButtonsGroupSize = mButtonsGroup.layoutParams + mExpandedButtonsGroupSize = mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams + mButtonsGroup.layoutParams = ConstraintLayout.LayoutParams(mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams) + mButtonsGroup.layoutParams.width = resources.getDimension(R.dimen.page_link_buttons_size).toInt() + mCollapseButtonsGroupSize = mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams mScrollUp.visibility = View.GONE mScrollDown.visibility = View.GONE @@ -252,18 +255,9 @@ class PagesLinkFragment : Fragment() { mHelp.setOnClickListener { if (mHandler.hasCallbacks(mReduceSizeGroupButton)) mHandler.removeCallbacks(mReduceSizeGroupButton) - mHandler.postDelayed(mReduceSizeGroupButton, 3000) - - mButtonsGroup.layoutParams = ConstraintLayout.LayoutParams( - LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT - ) - - mButtonsGroup.updateLayoutParams { - startToStart = mRoot.id - bottomToTop = mContentButton.id - } + mHandler.postDelayed(mReduceSizeGroupButton, 5000) + ComponentsUtil.changeWidthAnimateSize(mButtonsGroup, mExpandedButtonsGroupSize, false) changColorButton(requireContext().getColor(R.color.file_link_buttons_expanded)) } diff --git a/app/src/main/res/layout-sw600dp/fragment_pages_link.xml b/app/src/main/res/layout-sw600dp/fragment_pages_link.xml index 9e388543..14c731d2 100644 --- a/app/src/main/res/layout-sw600dp/fragment_pages_link.xml +++ b/app/src/main/res/layout-sw600dp/fragment_pages_link.xml @@ -156,7 +156,7 @@ Date: Wed, 29 Jun 2022 12:31:33 -0300 Subject: [PATCH 08/28] Ajuste de layout e cores. --- app/release/output-metadata.json | 6 ++-- .../view/components/ComponentsUtil.kt | 2 +- .../view/ui/reader/ReaderFragment.kt | 3 +- .../drawable-v21/history_custom_ripple.xml | 2 +- .../main/res/layout-land/activity_reader.xml | 26 ++++++++-------- .../res/layout-land/fragment_pages_link.xml | 22 ++++++------- .../main/res/layout-land/page_link_card.xml | 6 ++-- .../res/layout-land/page_not_link_card.xml | 2 +- .../layout-sw600dp-land/activity_reader.xml | 27 ++++++++-------- .../layout-sw600dp-land/page_link_card.xml | 6 ++-- .../res/layout-sw600dp/activity_reader.xml | 29 +++++++++-------- .../layout-sw600dp/fragment_manga_detail.xml | 8 ++--- .../layout-sw600dp/fragment_pages_link.xml | 22 ++++++------- .../res/layout-sw600dp/page_link_card.xml | 6 ++-- .../res/layout-sw600dp/page_not_link_card.xml | 2 +- .../res/layout/activity_main_bar_menu.xml | 4 +-- .../main/res/layout/activity_pages_link.xml | 1 + app/src/main/res/layout/activity_reader.xml | 31 +++++++++---------- app/src/main/res/layout/floating_buttons.xml | 12 +++---- .../res/layout/floating_subtitle_reader.xml | 8 ++--- .../main/res/layout/fragment_manga_detail.xml | 8 ++--- .../main/res/layout/fragment_pages_link.xml | 22 ++++++------- app/src/main/res/layout/history_card.xml | 2 +- app/src/main/res/layout/manga_grid_card.xml | 2 +- app/src/main/res/layout/page_link_card.xml | 6 ++-- .../main/res/layout/page_not_link_card.xml | 2 +- .../main/res/layout/popup_subtitle_reader.xml | 10 +++--- app/src/main/res/values/colors.xml | 11 +++++-- app/src/main/res/values/dimens.xml | 2 +- app/src/main/res/values/styles.xml | 12 ++++++- app/src/main/res/values/styles_alert.xml | 2 +- 31 files changed, 160 insertions(+), 144 deletions(-) diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index ef10e327..0353a039 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -11,9 +11,9 @@ "type": "SINGLE", "filters": [], "attributes": [], - "versionCode": 11, - "versionName": "2.11", - "outputFile": "BilingualManga_2.11-release.apk" + "versionCode": 12, + "versionName": "2.12", + "outputFile": "BilingualManga_2.12-release.apk" } ], "elementType": "File" diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt index 75188c09..5580ec3c 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/components/ComponentsUtil.kt @@ -71,7 +71,7 @@ class ComponentsUtil { val finalWidth = finalLayout.width val initialWidth = if (isInitialExpanded) view.width - finalLayout.width else view.width - + val animation: Animation = object : Animation() { override fun applyTransformation(interpolatedTime: Float, t: Transformation?) { if (interpolatedTime >= 1f) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderFragment.kt index 12d61591..642a6f48 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderFragment.kt @@ -45,6 +45,7 @@ import br.com.fenix.bilingualmangareader.util.helpers.Util import br.com.fenix.bilingualmangareader.view.components.PageImageView import br.com.fenix.bilingualmangareader.view.components.PageViewPager import br.com.fenix.bilingualmangareader.view.managers.MangaHandler +import com.google.android.material.appbar.AppBarLayout import com.google.android.material.button.MaterialButton import com.squareup.picasso.MemoryPolicy import com.squareup.picasso.Picasso @@ -62,7 +63,7 @@ class ReaderFragment : Fragment(), View.OnTouchListener { private val mViewModel: ReaderViewModel by activityViewModels() private lateinit var mRoot: CoordinatorLayout - private lateinit var mToolbarTop: LinearLayout + private lateinit var mToolbarTop: AppBarLayout private lateinit var mPageNavLayout: LinearLayout private lateinit var mPopupSubtitle: FrameLayout private lateinit var mPopupColor: FrameLayout diff --git a/app/src/main/res/drawable-v21/history_custom_ripple.xml b/app/src/main/res/drawable-v21/history_custom_ripple.xml index efcdbe4e..56ed2536 100644 --- a/app/src/main/res/drawable-v21/history_custom_ripple.xml +++ b/app/src/main/res/drawable-v21/history_custom_ripple.xml @@ -1,6 +1,6 @@ + android:color="@color/ripple_color"> diff --git a/app/src/main/res/layout-land/activity_reader.xml b/app/src/main/res/layout-land/activity_reader.xml index 2f6bfafd..2d7cfc09 100644 --- a/app/src/main/res/layout-land/activity_reader.xml +++ b/app/src/main/res/layout-land/activity_reader.xml @@ -20,12 +20,12 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - + android:background="@drawable/main_toolbar_background" + android:theme="@style/ToolbarContentTheme" > - + + app:rippleColor="@color/ripple_color" />