Skip to content

Commit c3b4acf

Browse files
cmaierFabtron
andauthored
Add Developer Settings to the Profile Screen (#88)
Developer settings has been added that can be enabled by tapping the Version info five consecutive times and entering the password `Password`. The following options are available: * Backend * AppUser-ID _(copy-on-click)_ * Client-ID _(copy-on-click)_ * Environment _(choose-on-click, app restart necessary)_ * App * Reset App-User-ID _(Button, resets AppUser-ID, app restart necessary)_ * Reset Client-ID _(Button, resets Client-ID, app restart necessary)_ Co-authored-by: Fabian Bender <[email protected]>
1 parent 4c53463 commit c3b4acf

File tree

54 files changed

+1389
-121
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1389
-121
lines changed

kotlin-sample/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ dependencies {
9393

9494
implementation 'com.google.android.material:material:1.6.1'
9595

96+
implementation 'com.jakewharton:process-phoenix:2.1.2'
97+
9698
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
9799

98100
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
@@ -101,4 +103,5 @@ dependencies {
101103
testImplementation 'junit:junit:4.13.2'
102104
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
103105
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
106+
104107
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"configuration": {
3+
"image": "",
4+
"style": "scroll",
5+
"padding": [0]
6+
},
7+
"widgets": [
8+
{
9+
"type": "section",
10+
"id": "section1",
11+
"header": "Backend",
12+
"padding": [0, 16, 8, 0],
13+
"items": [
14+
{
15+
"type": "snabble.clientId",
16+
"id": "clientId",
17+
"padding": [16, 0]
18+
},
19+
{
20+
"type": "snabble.appUserId",
21+
"id": "appUserId",
22+
"padding": [16, 0]
23+
},
24+
{
25+
"type": "snabble.switchEnvironment",
26+
"id": "io.snabble.environment",
27+
"text": "Profile.environment",
28+
"padding": [16, 0],
29+
"values": [
30+
{
31+
"id": "io.snabble.environment.production",
32+
"text": "Profile.Environment.production"
33+
},
34+
{
35+
"id": "io.snabble.environment.staging",
36+
"text": "Profile.Environment.staging"
37+
},
38+
{
39+
"id": "io.snabble.environment.testing",
40+
"text": "Profile.Environment.testing"
41+
}
42+
]
43+
}
44+
]
45+
},
46+
{
47+
"type": "section",
48+
"id": "section1",
49+
"header": "App",
50+
"padding": [0, 16, 8, 0],
51+
"items": [
52+
{
53+
"type": "button",
54+
"id": "resetAppUserId",
55+
"text": "Reset AppUser-ID",
56+
"padding": [16, 8]
57+
},
58+
{
59+
"type": "button",
60+
"id": "resetClientId",
61+
"text": "Reset Client-ID",
62+
"padding": [16, 8]
63+
}
64+
]
65+
}
66+
]
67+
}

kotlin-sample/src/main/assets/profileConfig.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@
5656
"text": "Profile.pushMessages",
5757
"key": "io.snabble.sample.pushMessages",
5858
"padding": [16, 6]
59+
},
60+
{
61+
"type": "snabble.devSettings",
62+
"id": "devSettings",
63+
"text": "Profile.developerMode",
64+
"padding": [16, 8]
5965
}
6066
]
6167
},
@@ -91,7 +97,7 @@
9197
},
9298
{
9399
"type": "snabble.version",
94-
"id": "5",
100+
"id": "version",
95101
"padding": [16, 8]
96102
}
97103
]

kotlin-sample/src/main/java/io/snabble/sdk/sample/LoadingActivity.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import android.content.Intent
44
import android.os.Bundle
55
import androidx.appcompat.app.AlertDialog
66
import androidx.appcompat.app.AppCompatActivity
7-
import io.snabble.sdk.Environment
8-
97
import io.snabble.sdk.InitializationState
108
import io.snabble.sdk.Snabble
119

@@ -17,14 +15,13 @@ class LoadingActivity : AppCompatActivity() {
1715
}
1816

1917
private fun initSdk() {
20-
Snabble.userPreferences.environment = Environment.STAGING
21-
2218
Snabble.setDebugLoggingEnabled(BuildConfig.DEBUG)
2319
Snabble.initializationState.observe(this) {
2420
when (it) {
2521
InitializationState.UNINITIALIZED,
2622
InitializationState.INITIALIZING,
27-
null -> {
23+
null,
24+
-> {
2825
}
2926
InitializationState.INITIALIZED -> {
3027
startActivity(Intent(this@LoadingActivity, MainActivity::class.java))

kotlin-sample/src/main/java/io/snabble/sdk/sample/MainActivity.kt

Lines changed: 113 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package io.snabble.sdk.sample
22

33
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import android.content.DialogInterface
46
import android.content.SharedPreferences
57
import android.os.Bundle
68
import androidx.activity.viewModels
9+
import androidx.appcompat.app.AlertDialog
710
import androidx.appcompat.app.AppCompatActivity
811
import androidx.appcompat.widget.Toolbar
912
import androidx.core.os.bundleOf
@@ -18,14 +21,20 @@ import androidx.navigation.ui.setupWithNavController
1821
import androidx.preference.PreferenceManager
1922
import com.google.android.material.navigation.NavigationBarView
2023
import com.google.gson.Gson
24+
import com.jakewharton.processphoenix.ProcessPhoenix
25+
import io.snabble.sdk.Environment
2126
import io.snabble.sdk.Snabble
2227
import io.snabble.sdk.SnabbleUiToolkit
2328
import io.snabble.sdk.SnabbleUiToolkit.Event.SHOW_RECEIPT_LIST
29+
import io.snabble.sdk.dynamicview.viewmodel.DynamicAction
2430
import io.snabble.sdk.sample.onboarding.repository.OnboardingRepository
2531
import io.snabble.sdk.sample.onboarding.repository.OnboardingRepositoryImpl
32+
import io.snabble.sdk.screens.devsettings.viewmodel.DevSettingsViewModel
2633
import io.snabble.sdk.screens.home.viewmodel.DynamicHomeViewModel
2734
import io.snabble.sdk.screens.profile.viewmodel.DynamicProfileViewModel
2835
import io.snabble.sdk.screens.receipts.showDetails
36+
import io.snabble.sdk.widgets.snabble.devsettings.login.ui.DevSettingsLoginFragment
37+
import io.snabble.sdk.widgets.snabble.devsettings.login.viewmodel.DevSettingsLoginViewModel
2938
import kotlinx.coroutines.launch
3039

3140
class MainActivity : AppCompatActivity() {
@@ -53,55 +62,34 @@ class MainActivity : AppCompatActivity() {
5362

5463
private val homeViewModel: DynamicHomeViewModel by viewModels()
5564
private val profileViewModel: DynamicProfileViewModel by viewModels()
65+
private val devSettingsLoginViewModel: DevSettingsLoginViewModel by viewModels()
66+
private val devSettingsViewModel: DevSettingsViewModel by viewModels()
5667

5768
private val onboardingRepo: OnboardingRepository by lazy {
5869
OnboardingRepositoryImpl(assets, Gson())
5970
}
6071

72+
private lateinit var navBarView: NavigationBarView
73+
6174
override fun onCreate(savedInstanceState: Bundle?) {
6275
super.onCreate(savedInstanceState)
63-
6476
setContentView(R.layout.activity_main)
6577

6678
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
6779
val navController = navHostFragment.navController
68-
val navBarView: NavigationBarView = findViewById(R.id.nav_view)
80+
navBarView = findViewById(R.id.nav_view)
6981

7082
navBarView.setupWithNavController(navController)
7183

7284
val toolbar: Toolbar = findViewById(R.id.toolbar)
7385
setupToolbar(toolbar, navController, navBarView)
7486
setUpUiEvents(this, navController, navBarView)
7587

76-
profileViewModel.actions.asLiveData()
77-
.observe(this) { action ->
78-
when (action.widget.id) {
79-
"show.lastPurchases" -> SnabbleUiToolkit.executeAction(context = this, SHOW_RECEIPT_LIST)
80-
else -> Unit
81-
}
82-
}
83-
84-
homeViewModel.actions.asLiveData()
85-
.observe(this) { action ->
86-
when (action.widget.id) {
87-
"start" -> navBarView.selectedItemId = R.id.navigation_scanner
88-
"stores" -> navBarView.selectedItemId = R.id.navigation_shop
89-
"purchases" -> {
90-
when (action.info?.get("action")) {
91-
"more" -> SnabbleUiToolkit.executeAction(context = this, SHOW_RECEIPT_LIST)
92-
93-
"purchase" -> {
94-
(action.info?.get("id") as? String)?.let {
95-
lifecycleScope.launch {
96-
showDetails(this@MainActivity.findViewById(android.R.id.content), it)
97-
}
98-
}
99-
}
100-
}
101-
}
102-
else -> Unit
103-
}
104-
}
88+
homeViewModel.actions.asLiveData().observe(this, ::handleHomeScreenAction)
89+
profileViewModel.actions.asLiveData().observe(this) {
90+
handleProfileScreenAction(it, navController)
91+
}
92+
devSettingsViewModel.actions.asLiveData().observe(this, ::handleDevSettingsScreenAction)
10593

10694
if (savedInstanceState == null && showOnboarding != false) {
10795
lifecycleScope.launch {
@@ -128,6 +116,98 @@ class MainActivity : AppCompatActivity() {
128116
Snabble.checkInManager.stopUpdating()
129117
}
130118

119+
private fun handleHomeScreenAction(action: DynamicAction) {
120+
when (action.widget.id) {
121+
"start" -> navBarView.selectedItemId = R.id.navigation_scanner
122+
"stores" -> navBarView.selectedItemId = R.id.navigation_shop
123+
"purchases" -> {
124+
when (action.info?.get("action")) {
125+
"more" -> SnabbleUiToolkit.executeAction(context = this, SHOW_RECEIPT_LIST)
126+
127+
"purchase" -> {
128+
(action.info?.get("id") as? String)?.let {
129+
lifecycleScope.launch {
130+
showDetails(this@MainActivity.findViewById(android.R.id.content), it)
131+
}
132+
}
133+
}
134+
}
135+
}
136+
else -> Unit
137+
}
138+
}
139+
140+
private fun handleProfileScreenAction(action: DynamicAction, navController: NavController) {
141+
when (action.widget.id) {
142+
"show.lastPurchases" -> SnabbleUiToolkit.executeAction(context = this, SHOW_RECEIPT_LIST)
143+
144+
"devSettings" -> navController.navigate(R.id.dev_settings)
145+
146+
"version" -> {
147+
devSettingsLoginViewModel.incClickCount()
148+
if (devSettingsLoginViewModel.clickCount.value == NUMBER_OF_NEEDED_VERSION_CLICKS) {
149+
DevSettingsLoginFragment().show(supportFragmentManager, "DevSettingsPasswordDialog")
150+
}
151+
}
152+
else -> Unit
153+
}
154+
}
155+
156+
private fun handleDevSettingsScreenAction(action: DynamicAction) {
157+
when (action.widget.id) {
158+
"io.snabble.environment" -> {
159+
val environment = when (action.info?.get("selection")) {
160+
"io.snabble.environment.production" -> {
161+
Environment.PRODUCTION
162+
}
163+
"io.snabble.environment.staging" -> {
164+
Environment.STAGING
165+
}
166+
"io.snabble.environment.testing" -> {
167+
Environment.TESTING
168+
}
169+
else -> return
170+
}
171+
if (environment != Snabble.environment) {
172+
showWarningDialog(
173+
msg = "Do you really want to switch from ${Snabble.environment} to $environment?"
174+
) {
175+
Snabble.userPreferences.environment = environment
176+
ProcessPhoenix.triggerRebirth(this)
177+
}
178+
}
179+
}
180+
181+
"resetAppUserId" -> {
182+
showWarningDialog(msg = "Do you really want to reset your AppUser-ID?") {
183+
Snabble.userPreferences.appUser = null
184+
ProcessPhoenix.triggerRebirth(this)
185+
}
186+
}
187+
188+
"resetClientId" -> {
189+
showWarningDialog(msg = "Do you really want to reset your Client-ID?") {
190+
getSharedPreferences("snabble_prefs", Context.MODE_PRIVATE).edit()
191+
.putString("Client-ID", null)
192+
.apply()
193+
ProcessPhoenix.triggerRebirth(this)
194+
}
195+
}
196+
197+
else -> Unit
198+
}
199+
}
200+
201+
private fun showWarningDialog(msg: String, action: () -> Unit) =
202+
AlertDialog.Builder(this)
203+
.setTitle("Warning")
204+
.setMessage(msg)
205+
.setPositiveButton("Yes") { _: DialogInterface?, _: Int ->
206+
action()
207+
}
208+
.setNegativeButton("No", null)
209+
.show()
210+
131211
// Can be used to get args from deeplinks. In this case the args are used to
132212
private fun NavController.setup(toolbar: Toolbar, navBarView: NavigationBarView) {
133213
addOnDestinationChangedListener { _, destination, arguments ->
@@ -164,6 +244,8 @@ class MainActivity : AppCompatActivity() {
164244

165245
companion object {
166246

247+
private const val NUMBER_OF_NEEDED_VERSION_CLICKS = 5
248+
167249
const val PREF_KEY_SHOW_ONBOARDING = "snabble.show.onboarding"
168250
}
169251
}

kotlin-sample/src/main/res/navigation/mobile_navigation.xml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,21 @@
6464

6565
</fragment>
6666

67-
<fragment
67+
<navigation
6868
android:id="@+id/navigation_profile"
69-
android:name="io.snabble.sdk.screens.profile.ui.ProfileFragment"
70-
android:label="@string/profile" />
69+
app:startDestination="@id/navigation_profile_tab">
70+
71+
<fragment
72+
android:id="@+id/navigation_profile_tab"
73+
android:name="io.snabble.sdk.screens.profile.ui.ProfileFragment"
74+
android:label="@string/profile" />
75+
76+
<fragment
77+
android:id="@+id/dev_settings"
78+
android:name="io.snabble.sdk.screens.devsettings.ui.DevSettingsFragment"
79+
android:label="@string/Profile.developerMode" />
80+
81+
</navigation>
7182

7283
<navigation
7384
android:id="@id/navigation_scanner"

kotlin-sample/src/main/res/values-night/colors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<color name="grey">#8E8E93</color>
2222
<color name="almost_white">#FDFFFF</color>
2323
<color name="home_background">@color/windowBackground</color>
24+
<color name="dev_background">@color/windowBackground</color>
2425
<color name="profile_background">@color/windowBackground</color>
2526
<color name="snabble_onboarding_primary">@color/snabbleBlue</color>
2627
<color name="snabble_onboarding_highlight">#005982</color>

kotlin-sample/src/main/res/values/colors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<color name="black">#FF000000</color>
2323
<color name="almost_white">#FDFFFF</color>
2424
<color name="profile_background">@color/windowBackground</color>
25+
<color name="dev_background">@color/windowBackground</color>
2526
<color name="home_background">@color/windowBackground</color>
2627
<color name="snabble_onboarding_primary">@color/snabbleBlue</color>
2728
<color name="snabble_onboarding_highlight">#005982</color>

ui-toolkit/src/main/kotlin/io/snabble/sdk/wlanmanager/data/Result.kt renamed to ui-toolkit/src/main/kotlin/io/snabble/sdk/data/Result.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.snabble.sdk.wlanmanager.data
1+
package io.snabble.sdk.data
22

33
internal sealed interface Result {
44

0 commit comments

Comments
 (0)