Skip to content

Commit

Permalink
Merge pull request #190 from hotwired/form-submission-status
Browse files Browse the repository at this point in the history
Implement the form submission adapter APIs
  • Loading branch information
jayohms authored Oct 20, 2021
2 parents 947c188 + 83111ca commit f01b3b5
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.hotwire.turbo.demo.base

import android.net.Uri
import android.view.MenuItem
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsIntent.SHARE_STATE_ON
Expand All @@ -11,10 +12,12 @@ import dev.hotwire.turbo.config.context
import dev.hotwire.turbo.demo.R
import dev.hotwire.turbo.demo.util.BASE_URL
import dev.hotwire.turbo.nav.TurboNavDestination
import dev.hotwire.turbo.nav.TurboNavPresentationContext
import dev.hotwire.turbo.nav.TurboNavPresentationContext.*
import dev.hotwire.turbo.nav.TurboNavPresentationContext.MODAL

interface NavDestination : TurboNavDestination {
val menuProgress: MenuItem?
get() = toolbarForNavigation()?.menu?.findItem(R.id.menu_progress)

override fun shouldNavigateTo(newLocation: String): Boolean {
return when (isNavigable(newLocation)) {
true -> true
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
package dev.hotwire.turbo.demo.features.web

import android.os.Bundle
import android.view.View
import dev.hotwire.turbo.demo.R
import dev.hotwire.turbo.demo.base.NavDestination
import dev.hotwire.turbo.fragments.TurboWebBottomSheetDialogFragment
import dev.hotwire.turbo.nav.TurboNavGraphDestination

@TurboNavGraphDestination(uri = "turbo://fragment/web/modal/sheet")
class WebBottomSheetFragment : TurboWebBottomSheetDialogFragment(), NavDestination
class WebBottomSheetFragment : TurboWebBottomSheetDialogFragment(), NavDestination {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupMenu()
}

override fun onFormSubmissionStarted(location: String) {
menuProgress?.isVisible = true
}

override fun onFormSubmissionFinished(location: String) {
menuProgress?.isVisible = false
}

private fun setupMenu() {
toolbarForNavigation()?.inflateMenu(R.menu.web)
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,38 @@
package dev.hotwire.turbo.demo.features.web

import android.os.Bundle
import android.view.View
import dev.hotwire.turbo.demo.R
import dev.hotwire.turbo.demo.base.NavDestination
import dev.hotwire.turbo.demo.util.SIGN_IN_URL
import dev.hotwire.turbo.fragments.TurboWebFragment
import dev.hotwire.turbo.nav.TurboNavGraphDestination
import dev.hotwire.turbo.visit.TurboVisitAction
import dev.hotwire.turbo.visit.TurboVisitAction.REPLACE
import dev.hotwire.turbo.visit.TurboVisitOptions

@TurboNavGraphDestination(uri = "turbo://fragment/web")
open class WebFragment : TurboWebFragment(), NavDestination {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupMenu()
}

override fun onFormSubmissionStarted(location: String) {
menuProgress?.isVisible = true
}

override fun onFormSubmissionFinished(location: String) {
menuProgress?.isVisible = false
}

override fun onVisitErrorReceived(location: String, errorCode: Int) {
when (errorCode) {
401 -> navigate(SIGN_IN_URL, TurboVisitOptions(action = REPLACE))
else -> super.onVisitErrorReceived(location, errorCode)
}
}

private fun setupMenu() {
toolbarForNavigation()?.inflateMenu(R.menu.web)
}
}
13 changes: 13 additions & 0 deletions demo/src/main/res/layout/toolbar_progress.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent">

<ProgressBar
android:layout_width="40dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:layout_marginEnd="12dp"
android:indeterminateTint="?colorSecondary" />

</FrameLayout>
14 changes: 14 additions & 0 deletions demo/src/main/res/menu/web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<item
android:id="@+id/menu_progress"
android:title="@string/menu_progress"
android:visible="false"
app:actionLayout="@layout/toolbar_progress"
app:showAsAction="always"
tools:ignore="AlwaysShowAction" />

</menu>
1 change: 1 addition & 0 deletions demo/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
<string name="app_name">Turbo Native</string>
<string name="error_web_home">Error loading page</string>
<string name="error_web_home_description">The demo server may be starting up. Pull-to-refresh to try again in a minute.</string>
<string name="menu_progress">Loading…</string>
</resources>
8 changes: 8 additions & 0 deletions turbo/src/main/assets/js/turbo_bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@
})
}

formSubmissionStarted(formSubmission) {
TurboSession.formSubmissionStarted(formSubmission.location.toString())
}

formSubmissionFinished(formSubmission) {
TurboSession.formSubmissionFinished(formSubmission.location.toString())
}

pageInvalidated() {
TurboSession.pageInvalidated()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.core.content.edit
import dev.hotwire.turbo.http.TurboHttpClient
import dev.hotwire.turbo.util.dispatcherProvider
import dev.hotwire.turbo.util.toJson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.Request
import java.io.IOException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ internal class TurboWebFragmentDelegate(
return navDestination
}

override fun formSubmissionStarted(location: String) {
callback.onFormSubmissionStarted(location)
}

override fun formSubmissionFinished(location: String) {
callback.onFormSubmissionFinished(location)
}

// -----------------------------------------------------------------------
// Private
// -----------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ interface TurboWebFragmentCallback {
*/
fun onVisitErrorReceived(location: String, errorCode: Int) {}

/**
* Called when a Turbo form submission has started.
*/
fun onFormSubmissionStarted(location: String) {}

/**
* Called when a Turbo form submission has finished.
*/
fun onFormSubmissionFinished(location: String) {}

/**
* Called when the Turbo visit resulted in an error, but a cached
* snapshot is being displayed, which may be stale.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import dev.hotwire.turbo.config.*
import dev.hotwire.turbo.session.TurboSessionModalResult
import dev.hotwire.turbo.visit.TurboVisitAction
import dev.hotwire.turbo.visit.TurboVisitOptions
import java.net.URI

@Suppress("MemberVisibilityCanBePrivate")
internal class TurboNavRule(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import android.os.Build
import android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
import android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
import android.view.Window
import android.view.WindowInsetsController
import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
import androidx.annotation.RequiresApi
import androidx.lifecycle.Lifecycle
Expand Down
40 changes: 40 additions & 0 deletions turbo/src/main/kotlin/dev/hotwire/turbo/session/TurboSession.kt
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,46 @@ class TurboSession internal constructor(
}
}

/**
* Called by Turbo bridge when a form submission has started.
*
* Warning: This method is public so it can be used as a Javascript Interface.
* You should never call this directly as it could lead to unintended behavior.
*
* @param location The location of the form submission.
*/
@JavascriptInterface
fun formSubmissionStarted(location: String) {
logEvent(
"formSubmissionStarted",
"location" to location
)

currentVisit?.let {
callback { it.formSubmissionStarted(location) }
}
}

/**
* Called by Turbo bridge when a form submission has finished.
*
* Warning: This method is public so it can be used as a Javascript Interface.
* You should never call this directly as it could lead to unintended behavior.
*
* @param location The location of the form submission.
*/
@JavascriptInterface
fun formSubmissionFinished(location: String) {
logEvent(
"formSubmissionFinished",
"location" to location
)

currentVisit?.let {
callback { it.formSubmissionFinished(location) }
}
}

/**
* Called when Turbo bridge detects that the page being visited has been invalidated,
* typically by new resources in the the page HEAD.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ internal interface TurboSessionCallback {
fun visitLocationStarted(location: String)
fun visitProposedToLocation(location: String, options: TurboVisitOptions)
fun visitNavDestination(): TurboNavDestination
fun formSubmissionStarted(location: String)
fun formSubmissionFinished(location: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,22 @@ class TurboSessionTest {
assertThat(session.restorationIdentifiers.size()).isEqualTo(1)
}

@Test
fun visitFormSubmissionStartedFiresCallback() {
session.currentVisit = visit
session.formSubmissionStarted(visit.location)

verify(callback).formSubmissionStarted(visit.location)
}

@Test
fun visitFormSubmissionFinishedFiresCallback() {
session.currentVisit = visit
session.formSubmissionFinished(visit.location)

verify(callback).formSubmissionFinished(visit.location)
}

@Test
fun pageLoadedSavesRestorationIdentifier() {
val restorationIdentifier = "67890"
Expand Down

0 comments on commit f01b3b5

Please sign in to comment.