Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes of Display Navigation History #3239

Merged
merged 1 commit into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Kiwix Android
* Copyright (c) 2023 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.page.history

import androidx.test.espresso.web.sugar.Web.onWebView
import androidx.test.espresso.web.webdriver.DriverAtoms.findElement
import androidx.test.espresso.web.webdriver.DriverAtoms.webClick
import androidx.test.espresso.web.webdriver.Locator
import applyWithViewHierarchyPrinting
import com.adevinta.android.barista.interaction.BaristaSleepInteractions
import org.kiwix.kiwixmobile.BaseRobot
import org.kiwix.kiwixmobile.Findable.StringId.TextId
import org.kiwix.kiwixmobile.Findable.ViewId
import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.testutils.TestUtils

fun navigationHistory(func: NavigationHistoryRobot.() -> Unit) =
NavigationHistoryRobot().applyWithViewHierarchyPrinting(func)

class NavigationHistoryRobot : BaseRobot() {

fun checkZimFileLoadedSuccessful(readerFragment: Int) {
pauseForBetterTestPerformance()
isVisible(ViewId(readerFragment))
}

fun clickOnAndroidArticle() {
pauseForBetterTestPerformance()
onWebView()
.withElement(
findElement(
Locator.XPATH,
"//*[contains(text(), 'Android_(operating_system)')]"
)
)
.perform(webClick())
}

fun longClickOnBackwardButton() {
pauseForBetterTestPerformance()
longClickOn(ViewId(R.id.bottom_toolbar_arrow_back))
}

fun longClickOnForwardButton() {
pauseForBetterTestPerformance()
longClickOn(ViewId(R.id.bottom_toolbar_arrow_forward))
}

fun assertBackwardNavigationHistoryDialogDisplayed() {
pauseForBetterTestPerformance()
isVisible(TextId(R.string.backward_history))
}

fun clickOnBackwardButton() {
pauseForBetterTestPerformance()
clickOn(ViewId(R.id.bottom_toolbar_arrow_back))
}

fun assertForwardNavigationHistoryDialogDisplayed() {
pauseForBetterTestPerformance()
isVisible(TextId(R.string.forward_history))
}

fun clickOnDeleteHistory() {
pauseForBetterTestPerformance()
clickOn(ViewId(R.id.menu_pages_clear))
}

fun assertDeleteDialogDisplayed() {
pauseForBetterTestPerformance()
isVisible(TextId(R.string.clear_all_history_dialog_title))
}

private fun pauseForBetterTestPerformance() {
BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS_FOR_SEARCH_TEST.toLong())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Kiwix Android
* Copyright (c) 2023 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.kiwix.kiwixmobile.page.history

import android.os.Build
import androidx.core.content.edit
import androidx.core.net.toUri
import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario
import androidx.test.internal.runner.junit4.statement.UiThreadStatement
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import leakcanary.LeakAssertions
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.kiwix.kiwixmobile.BaseActivityTest
import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.nav.destination.library.LocalLibraryFragmentDirections
import org.kiwix.kiwixmobile.testutils.RetryRule
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream

class NavigationHistoryTest : BaseActivityTest() {

@Rule
@JvmField
var retryRule = RetryRule()

private lateinit var kiwixMainActivity: KiwixMainActivity

@Before
override fun waitForIdle() {
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).waitForIdle()
PreferenceManager.getDefaultSharedPreferences(context).edit {
putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, false)
putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false)
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
}
}

@Test
fun navigationHistoryDialogTest() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
ActivityScenario.launch(KiwixMainActivity::class.java).onActivity {
kiwixMainActivity = it
kiwixMainActivity.navigate(R.id.libraryFragment)
}
val loadFileStream =
NavigationHistoryTest::class.java.classLoader.getResourceAsStream("testzim.zim")
val zimFile = File(context.cacheDir, "testzim.zim")
if (zimFile.exists()) zimFile.delete()
zimFile.createNewFile()
loadFileStream.use { inputStream ->
val outputStream: OutputStream = FileOutputStream(zimFile)
outputStream.use { it ->
val buffer = ByteArray(inputStream.available())
var length: Int
while (inputStream.read(buffer).also { length = it } > 0) {
it.write(buffer, 0, length)
}
}
}
UiThreadStatement.runOnUiThread {
kiwixMainActivity.navigate(
LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader()
.apply { zimFileUri = zimFile.toUri().toString() }
)
}
navigationHistory {
checkZimFileLoadedSuccessful(R.id.readerFragment)
clickOnAndroidArticle()
longClickOnBackwardButton()
assertBackwardNavigationHistoryDialogDisplayed()
pressBack()
clickOnBackwardButton()
longClickOnForwardButton()
assertForwardNavigationHistoryDialogDisplayed()
clickOnDeleteHistory()
assertDeleteDialogDisplayed()
pressBack()
pressBack()
}
LeakAssertions.assertNoLeaks()
}
}

@After
fun setIsTestPreference() {
PreferenceManager.getDefaultSharedPreferences(context).edit {
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, false)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import org.kiwix.kiwixmobile.core.main.AddNoteDialog
import org.kiwix.kiwixmobile.core.page.bookmark.BookmarksFragment
import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects.ShowDeleteBookmarksDialog
import org.kiwix.kiwixmobile.core.page.history.HistoryFragment
import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryDialog
import org.kiwix.kiwixmobile.core.page.history.viewmodel.effects.ShowDeleteHistoryDialog
import org.kiwix.kiwixmobile.core.page.notes.NotesFragment
import org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects.ShowDeleteNotesDialog
Expand All @@ -51,6 +52,7 @@ interface CoreActivityComponent {
fun inject(addNoteDialog: AddNoteDialog)
fun inject(helpFragment: HelpFragment)
fun inject(notesFragment: NotesFragment)
fun inject(navigationHistoryDialog: NavigationHistoryDialog)

@Subcomponent.Builder
interface Builder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.animation.AnimationUtils
import android.webkit.WebBackForwardList
import android.webkit.WebView
import android.widget.Button
import android.widget.FrameLayout
Expand Down Expand Up @@ -107,11 +108,14 @@ import org.kiwix.kiwixmobile.core.main.MainMenu.MenuClickListener
import org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.DocumentSection
import org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.TableClickListener
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryClickListener
import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryDialog
import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudCallbacks
import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService
import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService.Companion.ACTION_PAUSE_OR_RESUME_TTS
import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService.Companion.ACTION_STOP_TTS
import org.kiwix.kiwixmobile.core.page.history.adapter.NavigationHistoryListItem
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.utils.AnimationUtils.rotate
Expand Down Expand Up @@ -150,7 +154,8 @@ abstract class CoreReaderFragment :
MenuClickListener,
FragmentActivityExtensions,
WebViewProvider,
ReadAloudCallbacks {
ReadAloudCallbacks,
NavigationHistoryClickListener {
protected val webViewList: MutableList<KiwixWebView> = ArrayList()
private val webUrlsProcessor = BehaviorProcessor.create<String>()

Expand Down Expand Up @@ -311,6 +316,7 @@ abstract class CoreReaderFragment :
private var unbinder: Unbinder? = null
private lateinit var serviceConnection: ServiceConnection
private var readAloudService: ReadAloudService? = null
private var navigationHistoryList: MutableList<NavigationHistoryListItem> = ArrayList()
override fun onActionModeStarted(
mode: ActionMode,
appCompatActivity: AppCompatActivity
Expand Down Expand Up @@ -674,6 +680,81 @@ abstract class CoreReaderFragment :
}
}

@OnLongClick(R2.id.bottom_toolbar_arrow_back)
fun showBackwardHistory() {
if (getCurrentWebView()?.canGoBack() == true) {
getCurrentWebView()?.copyBackForwardList()?.let { historyList ->
navigationHistoryList.clear()
(historyList.currentIndex downTo 0)
.asSequence()
.filter { it != historyList.currentIndex }
.forEach {
addItemToNavigationHistoryList(historyList, it)
}
showNavigationHistoryDialog(false)
}
}
}

@OnLongClick(R2.id.bottom_toolbar_arrow_forward)
fun showForwardHistory() {
if (getCurrentWebView()?.canGoForward() == true) {
getCurrentWebView()?.copyBackForwardList()?.let { historyList ->
navigationHistoryList.clear()
(historyList.currentIndex until historyList.size)
.asSequence()
.filter { it != historyList.currentIndex }
.forEach {
addItemToNavigationHistoryList(historyList, it)
}
showNavigationHistoryDialog(true)
}
}
}

private fun addItemToNavigationHistoryList(historyList: WebBackForwardList, index: Int) {
historyList.getItemAtIndex(index)?.let { webHistoryItem ->
navigationHistoryList.add(
NavigationHistoryListItem(
webHistoryItem.title,
webHistoryItem.url
)
)
}
}

/** Creates the full screen NavigationHistoryDialog, which is a DialogFragment */
private fun showNavigationHistoryDialog(isForwardHistory: Boolean) {
val fragmentTransaction = requireActivity().supportFragmentManager.beginTransaction()
val previousInstance =
requireActivity().supportFragmentManager.findFragmentByTag(NavigationHistoryDialog.TAG)

// To prevent multiple instances of the DialogFragment
if (previousInstance == null) {
/* Since the DialogFragment is never added to the back-stack, so findFragmentByTag()
* returning null means that the NavigationHistoryDialog is currently not on display (as doesn't exist)
**/
val dialogFragment = NavigationHistoryDialog(
if (isForwardHistory) getString(R.string.forward_history)
else getString(R.string.backward_history),
navigationHistoryList,
this
)
dialogFragment.show(fragmentTransaction, NavigationHistoryDialog.TAG)
// For DialogFragments, show() handles the fragment commit and display
}
}

override fun onItemClicked(navigationHistoryListItem: NavigationHistoryListItem) {
loadUrlWithCurrentWebview(navigationHistoryListItem.pageUrl)
}

override fun clearHistory() {
getCurrentWebView()?.clearHistory()
updateBottomToolbarArrowsAlpha()
toast(R.string.navigation_history_cleared)
}

@Suppress("MagicNumber")
private fun updateBottomToolbarArrowsAlpha() {
bottomToolbarArrowBack?.let {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Kiwix Android
* Copyright (c) 2023 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.kiwix.kiwixmobile.core.page.history

import org.kiwix.kiwixmobile.core.page.history.adapter.NavigationHistoryListItem

interface NavigationHistoryClickListener {
fun onItemClicked(navigationHistoryListItem: NavigationHistoryListItem)
fun clearHistory()
}
Loading