Skip to content

Commit 02186d5

Browse files
author
johndoe
committed
Visual overhaul: brand world for Probe and Pair screens
Dark stage, two-tone title, status cards with green/amber dots, primary/secondary buttons with TV focus rings and touch ripples, centered column on wide screens. Pair screen gains an SDK-token state row so users see what's staged before tapping. Logic untouched.
1 parent eae481d commit 02186d5

12 files changed

Lines changed: 594 additions & 92 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Unreleased
44

5+
- Visual overhaul: dark brand world (two-tone title, cards, status
6+
dots, amber/green prerequisite states), primary/secondary buttons
7+
with TV focus rings, centered column on wide screens. Pair screen
8+
shows SDK-token state before you tap.
9+
510
## 0.2.0 — one APK for every Android device
611

712
- minSdk 28 → 24, targetSdk 34 → 35; all four ABIs ship

‎app/src/main/java/ai/muse/gadgeteverywhere/PairActivity.kt‎

Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ package ai.muse.gadgeteverywhere
22

33
import android.app.Activity
44
import android.content.pm.PackageManager
5+
import android.graphics.Typeface
56
import android.os.Bundle
67
import android.view.Gravity
78
import android.view.View
89
import android.widget.Button
910
import android.widget.LinearLayout
10-
import android.widget.ScrollView
1111
import android.widget.TextView
1212
import com.chaquo.python.Python
1313
import java.io.File
@@ -18,44 +18,103 @@ class PairActivity : Activity() {
1818
private lateinit var status: TextView
1919
private lateinit var startButton: Button
2020
private lateinit var cancelButton: Button
21+
private lateinit var tokenValue: TextView
22+
private lateinit var tokenDot: View
2123
private var transport: BleTransport? = null
2224
@Volatile private var pairing = false
2325

2426
override fun onCreate(savedInstanceState: Bundle?) {
2527
super.onCreate(savedInstanceState)
28+
val (scroll, content) = Ui.screenFrame(this)
2629

27-
status = TextView(this).apply {
28-
textSize = 20f
29-
setPadding(48, 48, 48, 48)
30+
content.addView(
31+
TextView(this).apply {
32+
text = getString(R.string.pair_title)
33+
textSize = 28f
34+
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
35+
setTextColor(Ui.run { brand(R.color.ink) })
36+
setPadding(0, 0, 0, Ui.run { this@PairActivity.dp(16) })
37+
},
38+
)
39+
40+
// Token state card: users see BEFORE tapping whether the import
41+
// file is staged, instead of learning it from an error.
42+
val tokenCard = Ui.card(this)
43+
val (tokenRow, valueView) = Ui.statusRow(
44+
this, getString(R.string.pair_token_label),
45+
getString(R.string.pair_token_missing),
46+
Ui.run { brand(R.color.warn) },
47+
)
48+
tokenDot = tokenRow.getChildAt(0)
49+
tokenValue = valueView
50+
tokenCard.addView(tokenRow)
51+
content.addView(tokenCard)
52+
updateTokenRow()
53+
54+
val statusCard = Ui.card(this).apply {
55+
layoutParams = LinearLayout.LayoutParams(
56+
LinearLayout.LayoutParams.MATCH_PARENT,
57+
LinearLayout.LayoutParams.WRAP_CONTENT,
58+
).apply { topMargin = Ui.run { this@PairActivity.dp(12) } }
59+
}
60+
status = Ui.bodyText(this).apply {
3061
text = getString(R.string.pair_ready)
3162
}
32-
startButton = Button(this).apply {
33-
text = getString(R.string.pair_open_setup)
63+
statusCard.addView(status)
64+
content.addView(statusCard)
65+
66+
startButton = Ui.primaryButton(this, getString(R.string.pair_open_setup)).apply {
3467
setOnClickListener { startPairing() }
3568
}
36-
cancelButton = Button(this).apply {
37-
text = getString(R.string.pair_cancel)
69+
cancelButton = Ui.secondaryButton(this, getString(R.string.pair_cancel)).apply {
3870
setOnClickListener { finish() }
3971
}
40-
val buttons = LinearLayout(this).apply {
41-
orientation = LinearLayout.HORIZONTAL
42-
gravity = Gravity.CENTER
43-
addView(startButton)
44-
addView(cancelButton)
45-
}
46-
setContentView(
72+
content.addView(
4773
LinearLayout(this).apply {
48-
orientation = LinearLayout.VERTICAL
49-
// See ProbeActivity: stay below the status bar on 35+.
50-
fitsSystemWindows = true
51-
addView(buttons)
52-
addView(ScrollView(this@PairActivity).apply { addView(status) })
74+
orientation = LinearLayout.HORIZONTAL
75+
gravity = Gravity.CENTER
76+
layoutParams = LinearLayout.LayoutParams(
77+
LinearLayout.LayoutParams.MATCH_PARENT,
78+
LinearLayout.LayoutParams.WRAP_CONTENT,
79+
).apply { topMargin = Ui.run { this@PairActivity.dp(18) } }
80+
val gap = Ui.run { this@PairActivity.dp(10) }
81+
listOf(startButton, cancelButton).forEach {
82+
it.layoutParams = LinearLayout.LayoutParams(
83+
LinearLayout.LayoutParams.WRAP_CONTENT,
84+
LinearLayout.LayoutParams.WRAP_CONTENT,
85+
).apply { marginEnd = gap }
86+
addView(it)
87+
}
5388
},
5489
)
90+
91+
setContentView(scroll)
5592
startButton.requestFocus()
5693
ensurePermissions()
5794
}
5895

96+
/** Refresh the token row from the import file. Cheap; call on show
97+
* and after any import attempt (users stage the file between taps). */
98+
private fun updateTokenRow() {
99+
val staged = try {
100+
val dir = getExternalFilesDir("import")
101+
dir != null && File(dir, "muse_token.txt").let { it.exists() && it.readText().isNotBlank() }
102+
} catch (_: Exception) {
103+
false
104+
}
105+
tokenValue.text = getString(
106+
if (staged) R.string.pair_token_staged else R.string.pair_token_missing,
107+
)
108+
tokenDot.background = android.graphics.drawable.GradientDrawable().apply {
109+
shape = android.graphics.drawable.GradientDrawable.OVAL
110+
setColor(
111+
Ui.run {
112+
brand(if (staged) R.color.ok else R.color.warn)
113+
},
114+
)
115+
}
116+
}
117+
59118
private fun ensurePermissions() {
60119
val missing = Startup.missingBlePermissions(this)
61120
if (missing.isNotEmpty()) {
@@ -139,6 +198,7 @@ class PairActivity : Activity() {
139198
setStatus(getString(R.string.pair_token_saved))
140199
}
141200
}
201+
runOnUiThread { updateTokenRow() }
142202
if (sdkToken == null) {
143203
setStatus(getString(R.string.pair_no_token, importFile.absolutePath))
144204
pairing = false

0 commit comments

Comments
 (0)