Skip to content

Commit 73399bd

Browse files
authored
Add canGoBack() and canGoForward() into view state so it is accounted for (#302)
A regression meant that the view state was checked to see if it was identical to the last seen view state. If it was, rendering would skip. But for these forward/back buttons, they also relied on WebView state; not just the view state. So we were erroneously skipping updates for them because the view state was identical. The fix is to include these in the view state itself, meaning it won't skip the rendering if canGoBack() or canGoForward() has changed. onProgressChanged is the earliest place where the webView starts reporting the correct new states. But I've included the update in loadingFinished() too just in case onProgressChanged could be bypassed somehow.
1 parent d8c22e2 commit 73399bd

File tree

6 files changed

+30
-21
lines changed

6 files changed

+30
-21
lines changed

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,42 +237,42 @@ class BrowserTabViewModelTest {
237237

238238
@Test
239239
fun whenViewModelNotifiedThatWebViewHasFinishedLoadingThenViewStateIsUpdated() {
240-
testee.loadingFinished()
240+
testee.loadingFinished(null, false, false)
241241
assertFalse(loadingViewState().isLoading)
242242
}
243243

244244
@Test
245245
fun whenLoadingFinishedWithUrlThenSiteVisitedEntryAddedToLeaderboardDao() {
246246
testee.url.value = "http://example.com/abc"
247-
testee.loadingFinished()
247+
testee.loadingFinished(null, false, false)
248248
verify(mockNetworkLeaderboardDao).insert(SiteVisitedEntity("example.com"))
249249
}
250250

251251
@Test
252252
fun whenLoadingFinishedWithUrlThenOmnibarTextUpdatedToMatch() {
253253
val exampleUrl = "http://example.com/abc"
254-
testee.loadingFinished(exampleUrl)
254+
testee.loadingFinished(exampleUrl, false, false)
255255
assertEquals(exampleUrl, omnibarViewState().omnibarText)
256256
}
257257

258258
@Test
259259
fun whenLoadingFinishedWithQueryUrlThenOmnibarTextUpdatedToShowQuery() {
260260
val queryUrl = "http://duckduckgo.com?q=test"
261-
testee.loadingFinished(queryUrl)
261+
testee.loadingFinished(queryUrl, false, false)
262262
assertEquals("test", omnibarViewState().omnibarText)
263263
}
264264

265265
@Test
266266
fun whenLoadingFinishedWithNoUrlThenOmnibarTextUpdatedToMatch() {
267267
val exampleUrl = "http://example.com/abc"
268268
testee.urlChanged(exampleUrl)
269-
testee.loadingFinished(null)
269+
testee.loadingFinished(null, false, false)
270270
assertEquals(exampleUrl, omnibarViewState().omnibarText)
271271
}
272272

273273
@Test
274274
fun whenLoadingFinishedWithNoUrlThenSiteVisitedEntryNotAddedToLeaderboardDao() {
275-
testee.loadingFinished()
275+
testee.loadingFinished(null, false, false)
276276
verify(mockNetworkLeaderboardDao, never()).insert(SiteVisitedEntity("example.com"))
277277
}
278278

@@ -331,13 +331,13 @@ class BrowserTabViewModelTest {
331331

332332
@Test
333333
fun whenViewModelGetsProgressUpdateThenViewStateIsUpdated() {
334-
testee.progressChanged(0)
334+
testee.progressChanged(0, false, false)
335335
assertEquals(0, loadingViewState().progress)
336336

337-
testee.progressChanged(50)
337+
testee.progressChanged(50, false, false)
338338
assertEquals(50, loadingViewState().progress)
339339

340-
testee.progressChanged(100)
340+
testee.progressChanged(100, false, false)
341341
assertEquals(100, loadingViewState().progress)
342342
}
343343

app/src/main/java/com/duckduckgo/app/browser/BrowserChromeClient.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ class BrowserChromeClient @Inject constructor() : WebChromeClient() {
5050
customView = null
5151
}
5252

53-
override fun onProgressChanged(view: WebView, newProgress: Int) {
54-
webViewClientListener?.progressChanged(newProgress)
53+
override fun onProgressChanged(webView: WebView, newProgress: Int) {
54+
val canGoBack = webView.canGoBack()
55+
val canGoForward = webView.canGoForward()
56+
webViewClientListener?.progressChanged(newProgress, canGoBack, canGoForward)
5557
}
5658

5759
override fun onReceivedTitle(view: WebView, title: String) {

app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,8 @@ class BrowserTabFragment : Fragment(), FindListener {
817817

818818
private fun renderPopupMenus(browserShowing: Boolean, viewState: BrowserViewState) {
819819
popupMenu.contentView.apply {
820-
backPopupMenuItem.isEnabled = browserShowing && webView?.canGoBack() ?: false
821-
forwardPopupMenuItem.isEnabled = browserShowing && webView?.canGoForward() ?: false
820+
backPopupMenuItem.isEnabled = browserShowing && viewState.canGoBack
821+
forwardPopupMenuItem.isEnabled = browserShowing && viewState.canGoForward
822822
refreshPopupMenuItem.isEnabled = browserShowing
823823
newTabPopupMenuItem.isEnabled = browserShowing
824824
addBookmarksPopupMenuItem?.isEnabled = viewState.canAddBookmarks

app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ class BrowserTabViewModel(
9090
val showFireButton: Boolean = true,
9191
val showMenuButton: Boolean = true,
9292
val canSharePage: Boolean = false,
93-
val canAddBookmarks: Boolean = false
93+
val canAddBookmarks: Boolean = false,
94+
val canGoBack: Boolean = false,
95+
val canGoForward: Boolean = false
9496
)
9597

9698
data class OmnibarViewState(
@@ -244,11 +246,12 @@ class BrowserTabViewModel(
244246
autoCompleteViewState.value = AutoCompleteViewState(false)
245247
}
246248

247-
override fun progressChanged(newProgress: Int) {
249+
override fun progressChanged(newProgress: Int, canGoBack: Boolean, canGoForward: Boolean) {
248250
Timber.v("Loading in progress $newProgress")
249251

250252
val progress = currentLoadingViewState()
251253
loadingViewState.value = progress.copy(progress = newProgress)
254+
browserViewState.value = currentBrowserViewState().copy(canGoBack = canGoBack, canGoForward = canGoForward)
252255
}
253256

254257
override fun goFullScreen(view: View) {
@@ -271,7 +274,7 @@ class BrowserTabViewModel(
271274
onSiteChanged()
272275
}
273276

274-
override fun loadingFinished(url: String?) {
277+
override fun loadingFinished(url: String?, canGoBack: Boolean, canGoForward: Boolean) {
275278
Timber.v("Loading finished")
276279

277280
val currentOmnibarViewState = currentOmnibarViewState()
@@ -281,6 +284,7 @@ class BrowserTabViewModel(
281284

282285
loadingViewState.value = currentLoadingViewState.copy(isLoading = false)
283286
omnibarViewState.value = currentOmnibarViewState.copy(omnibarText = omnibarText)
287+
browserViewState.value = currentBrowserViewState().copy(canGoBack = canGoBack, canGoForward = canGoForward)
284288
registerSiteVisit()
285289
}
286290

app/src/main/java/com/duckduckgo/app/browser/BrowserWebViewClient.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,17 @@ class BrowserWebViewClient @Inject constructor(
7575
}
7676
}
7777

78-
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
78+
override fun onPageStarted(webView: WebView, url: String?, favicon: Bitmap?) {
7979
currentUrl = url
8080
webViewClientListener?.loadingStarted()
8181
webViewClientListener?.urlChanged(url)
8282
}
8383

84-
override fun onPageFinished(view: WebView?, url: String?) {
85-
webViewClientListener?.loadingFinished(url)
84+
override fun onPageFinished(webView: WebView, url: String?) {
85+
val canGoBack = webView.canGoBack()
86+
val canGoForward = webView.canGoForward()
87+
88+
webViewClientListener?.loadingFinished(url, canGoBack, canGoForward)
8689
}
8790

8891
@WorkerThread

app/src/main/java/com/duckduckgo/app/browser/WebViewClientListener.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import com.duckduckgo.app.trackerdetection.model.TrackingEvent
2424

2525
interface WebViewClientListener {
2626
fun loadingStarted()
27-
fun loadingFinished(url: String? = null)
28-
fun progressChanged(newProgress: Int)
27+
fun loadingFinished(url: String? = null, canGoBack: Boolean, canGoForward: Boolean)
28+
fun progressChanged(newProgress: Int, canGoBack: Boolean, canGoForward: Boolean)
2929
fun titleReceived(title: String)
3030
fun urlChanged(url: String?)
3131
fun trackerDetected(event: TrackingEvent)

0 commit comments

Comments
 (0)