Skip to content

Commit 4f7a1ba

Browse files
wip trying to implement jwilson's idea in workflow
1 parent 9056cc7 commit 4f7a1ba

File tree

11 files changed

+659
-0
lines changed

11 files changed

+659
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
plugins {
2+
id("com.android.application")
3+
id("kotlin-android")
4+
id("android-sample-app")
5+
id("android-ui-tests")
6+
id("kotlin-parcelize")
7+
}
8+
9+
android {
10+
defaultConfig {
11+
applicationId = "com.squareup.sample.thingy"
12+
}
13+
namespace = "com.squareup.sample.thingy"
14+
}
15+
16+
dependencies {
17+
debugImplementation(libs.squareup.leakcanary.android)
18+
19+
implementation(libs.androidx.activity.ktx)
20+
21+
implementation(project(":samples:containers:android"))
22+
implementation(project(":workflow-ui:core-android"))
23+
implementation(project(":workflow-ui:core-common"))
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<issues format="6" by="lint 7.4.1" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.1)" variant="all" version="7.4.1">
3+
4+
<issue
5+
id="UnusedAttribute"
6+
message="Attribute `autoSizeTextType` is only used in API level 26 and higher (current min is 21)"
7+
errorLine1=" android:autoSizeTextType=&quot;uniform&quot;"
8+
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
9+
<location
10+
file="src/main/res/layout/hello_back_button_layout.xml"
11+
line="12"
12+
column="7"/>
13+
</issue>
14+
15+
<issue
16+
id="DataExtractionRules"
17+
message="The attribute `android:allowBackup` is deprecated from Android 12 and higher and may be removed in future versions. Consider adding the attribute `android:dataExtractionRules` specifying an `@xml` resource which configures cloud backups and device transfers on Android 12 and higher."
18+
errorLine1=" android:allowBackup=&quot;false&quot;"
19+
errorLine2=" ~~~~~">
20+
<location
21+
file="src/main/AndroidManifest.xml"
22+
line="6"
23+
column="28"/>
24+
</issue>
25+
26+
</issues>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools">
4+
5+
<application
6+
android:allowBackup="false"
7+
android:label="@string/app_name"
8+
android:theme="@style/AppTheme"
9+
tools:ignore="GoogleAppIndexingWarning,MissingApplicationIcon"
10+
>
11+
12+
<activity android:name=".HelloBackButtonActivity"
13+
android:exported="true">
14+
15+
<intent-filter>
16+
<action android:name="android.intent.action.MAIN" />
17+
<category android:name="android.intent.category.LAUNCHER" />
18+
</intent-filter>
19+
20+
</activity>
21+
22+
</application>
23+
</manifest>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
@file:OptIn(WorkflowExperimentalRuntime::class)
2+
3+
package com.squareup.sample.thingy
4+
5+
import android.os.Bundle
6+
import androidx.activity.viewModels
7+
import androidx.appcompat.app.AppCompatActivity
8+
import androidx.lifecycle.SavedStateHandle
9+
import androidx.lifecycle.ViewModel
10+
import androidx.lifecycle.lifecycleScope
11+
import androidx.lifecycle.viewModelScope
12+
import com.squareup.sample.container.SampleContainers
13+
import com.squareup.workflow1.WorkflowExperimentalRuntime
14+
import com.squareup.workflow1.android.renderWorkflowIn
15+
import com.squareup.workflow1.config.AndroidRuntimeConfigTools
16+
import com.squareup.workflow1.ui.Screen
17+
import com.squareup.workflow1.ui.navigation.reportNavigation
18+
import com.squareup.workflow1.ui.withRegistry
19+
import com.squareup.workflow1.ui.workflowContentView
20+
import kotlinx.coroutines.Job
21+
import kotlinx.coroutines.flow.Flow
22+
import kotlinx.coroutines.flow.map
23+
import kotlinx.coroutines.launch
24+
import timber.log.Timber
25+
26+
private val viewRegistry = SampleContainers
27+
28+
class HelloBackButtonActivity : AppCompatActivity() {
29+
override fun onCreate(savedInstanceState: Bundle?) {
30+
super.onCreate(savedInstanceState)
31+
32+
val model: HelloBackButtonModel by viewModels()
33+
workflowContentView.take(lifecycle, model.renderings.map { it.withRegistry(viewRegistry) })
34+
35+
lifecycleScope.launch {
36+
model.waitForExit()
37+
finish()
38+
}
39+
}
40+
41+
companion object {
42+
init {
43+
Timber.plant(Timber.DebugTree())
44+
}
45+
}
46+
}
47+
48+
class HelloBackButtonModel(savedState: SavedStateHandle) : ViewModel() {
49+
private val running = Job()
50+
51+
val renderings: Flow<Screen> by lazy {
52+
renderWorkflowIn(
53+
workflow = TODO("MyWorkflow()"),
54+
scope = viewModelScope,
55+
savedStateHandle = savedState,
56+
runtimeConfig = AndroidRuntimeConfigTools.getAppWorkflowRuntimeConfig()
57+
) {
58+
// This workflow handles the back button itself, so the activity can't.
59+
// Instead, the workflow emits an output to signal that it's time to shut things down.
60+
running.complete()
61+
}.reportNavigation {
62+
Timber.i("Navigated to %s", it)
63+
}
64+
}
65+
66+
/** Blocks until the workflow signals that it's time to shut things down. */
67+
suspend fun waitForExit() = running.join()
68+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.squareup.sample.thingy
2+
3+
import com.squareup.workflow1.Workflow
4+
import com.squareup.workflow1.ui.Screen
5+
import kotlinx.coroutines.delay
6+
import kotlinx.coroutines.launch
7+
import kotlin.time.Duration.Companion.seconds
8+
9+
enum class MyOutputs {
10+
Back,
11+
Done,
12+
}
13+
14+
fun MyWorkflow(
15+
child1: Workflow<Unit, String, Screen>,
16+
child2: Workflow<Unit, String, Screen>,
17+
child3: Workflow<String, Nothing, Screen>,
18+
networkCall: suspend (String) -> String
19+
) = thingyWorkflow<String, MyOutputs> {
20+
21+
// Step 1
22+
showWorkflow(child1) { output ->
23+
when (output) {
24+
"back" -> emitOutput(MyOutputs.Back)
25+
"next" -> {
26+
// Step 2
27+
val childResult = showWorkflow(child2) { output ->
28+
if (output == "back") {
29+
// Removes child2 from the stack, cancels the output handler from step 1, and just
30+
// leaves child1 rendering.
31+
goBack()
32+
} else {
33+
finishWith(output)
34+
}
35+
}
36+
37+
// TODO: Show a loading screen automatically.
38+
val networkResult = networkCall(childResult)
39+
40+
// Step 3: Show a workflow for 3 seconds then finish.
41+
launch {
42+
delay(3.seconds)
43+
emitOutput(MyOutputs.Done)
44+
}
45+
showWorkflow(child3, networkResult) {}
46+
}
47+
48+
else -> {}
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)