Skip to content

Commit d0da257

Browse files
committed
Release 1.0.0 UI polish and refreshed screenshots
1 parent aa30fad commit d0da257

9 files changed

Lines changed: 147 additions & 87 deletions

File tree

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId = "com.thinkoff.clawwatch"
1212
minSdk = 30 // Wear OS 3 = API 30
1313
targetSdk = 34
14-
versionCode = 1
15-
versionName = "0.1.0"
14+
versionCode = 2
15+
versionName = "1.0.0"
1616
}
1717

1818
buildTypes {

app/src/main/java/com/thinkoff/clawwatch/MainActivity.kt

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import android.os.BatteryManager
99
import android.os.Bundle
1010
import android.os.SystemClock
1111
import android.util.Log
12+
import android.view.ViewConfiguration
1213
import android.view.MotionEvent
1314
import android.view.View
1415
import android.view.WindowManager
1516
import androidx.activity.result.contract.ActivityResultContracts
17+
import androidx.appcompat.app.AlertDialog
1618
import androidx.appcompat.app.AppCompatActivity
1719
import androidx.core.content.ContextCompat
1820
import androidx.lifecycle.lifecycleScope
@@ -41,6 +43,7 @@ class MainActivity : AppCompatActivity() {
4143
private const val AVATAR_SWIPE_THRESHOLD_DP = 24f
4244
private const val PREF_RAG_MODE = "rag_mode"
4345
private const val PREF_AVATAR_TYPE = "avatar_type"
46+
private const val PREF_LIVE_TEXT_ENABLED = "live_text_enabled"
4447
private const val ACCENT_COLOR = 0xFFD4A5E9.toInt()
4548
private const val LOW_BATTERY_COLOR = 0xFF9CA3AF.toInt()
4649
}
@@ -67,6 +70,7 @@ class MainActivity : AppCompatActivity() {
6770
private var avatarSwipeStartX = 0f
6871
private var avatarSwipeStartY = 0f
6972
private var avatarSwipeActive = false
73+
private var avatarTouchStartAt = 0L
7074

7175
private val requestMic = registerForActivityResult(
7276
ActivityResultContracts.RequestPermission()
@@ -294,6 +298,7 @@ class MainActivity : AppCompatActivity() {
294298
MotionEvent.ACTION_DOWN -> {
295299
avatarSwipeStartX = event.x
296300
avatarSwipeStartY = event.y
301+
avatarTouchStartAt = SystemClock.elapsedRealtime()
297302
avatarSwipeActive = true
298303
view.parent?.requestDisallowInterceptTouchEvent(true)
299304
true
@@ -312,6 +317,14 @@ class MainActivity : AppCompatActivity() {
312317
avatarSwipeActive = false
313318
val dx = event.x - avatarSwipeStartX
314319
val dy = event.y - avatarSwipeStartY
320+
val heldLong = (SystemClock.elapsedRealtime() - avatarTouchStartAt) >=
321+
ViewConfiguration.getLongPressTimeout()
322+
val mostlyStill = abs(dx) < threshold / 2 && abs(dy) < threshold / 2
323+
if (heldLong && mostlyStill) {
324+
showOptionsMenu()
325+
view.parent?.requestDisallowInterceptTouchEvent(false)
326+
return@setOnTouchListener true
327+
}
315328
if (abs(dx) > threshold && abs(dx) > abs(dy) * 1.2f) {
316329
if (dx > 0) finish() else nextAvatarType()
317330
}
@@ -328,6 +341,39 @@ class MainActivity : AppCompatActivity() {
328341
}
329342
}
330343

344+
private fun isLiveTextEnabled(): Boolean =
345+
prefs.getBoolean(PREF_LIVE_TEXT_ENABLED, false)
346+
347+
private fun showOptionsMenu() {
348+
val options = arrayOf("Demo live text: Off", "Demo live text: On")
349+
val selected = if (isLiveTextEnabled()) 1 else 0
350+
AlertDialog.Builder(this)
351+
.setTitle("Options")
352+
.setSingleChoiceItems(options, selected) { dialog, which ->
353+
prefs.edit().putBoolean(PREF_LIVE_TEXT_ENABLED, which == 1).apply()
354+
applyLiveTextVisibility()
355+
if (which == 1) {
356+
setStatus(when (state) {
357+
State.IDLE -> "Tap to talk"
358+
State.LISTENING -> "Listening…"
359+
State.THINKING -> "Thinking…"
360+
State.SEARCHING -> "Searching…"
361+
State.SPEAKING -> "Speaking…"
362+
State.ERROR -> "Error"
363+
State.SETUP -> "API key missing"
364+
})
365+
}
366+
dialog.dismiss()
367+
}
368+
.setNegativeButton("Cancel", null)
369+
.show()
370+
}
371+
372+
private fun applyLiveTextVisibility() {
373+
val show = isLiveTextEnabled() && state != State.SETUP
374+
binding.statusText.visibility = if (show) View.VISIBLE else View.GONE
375+
}
376+
331377
private fun avatarTypeKey(type: AvatarType): String = when (type) {
332378
AvatarType.ANT -> "ant"
333379
AvatarType.LOBSTER -> "lobster"
@@ -506,6 +552,7 @@ class MainActivity : AppCompatActivity() {
506552
binding.splashPanel.visibility = View.GONE
507553
binding.setupPanel.visibility = if (s == State.SETUP) View.VISIBLE else View.GONE
508554
binding.mainPanel.visibility = if (s != State.SETUP) View.VISIBLE else View.GONE
555+
applyLiveTextVisibility()
509556
updateAvatar(s)
510557
updateActionIndicator(s)
511558
binding.fab.contentDescription = when (s) {
@@ -556,7 +603,14 @@ class MainActivity : AppCompatActivity() {
556603
private fun formatStatus(msg: String): String =
557604
msg.trim().replace(Regex("\\s+"), " ").take(160)
558605

559-
private fun setStatus(msg: String) = runOnUiThread { binding.statusText.text = formatStatus(msg) }
606+
private fun setStatus(msg: String) = runOnUiThread {
607+
if (!isLiveTextEnabled() || state == State.SETUP) {
608+
binding.statusText.visibility = View.GONE
609+
return@runOnUiThread
610+
}
611+
binding.statusText.visibility = View.VISIBLE
612+
binding.statusText.text = formatStatus(msg)
613+
}
560614

561615
override fun onDestroy() {
562616
super.onDestroy()
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
3-
<solid android:color="#1A0A0A0F" />
4-
<stroke android:width="1dp" android:color="#66D4A5E9" />
3+
<solid android:color="#220A0A0F" />
54
<corners android:radius="12dp" />
65
</shape>

app/src/main/res/layout/activity_main.xml

Lines changed: 87 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -87,98 +87,105 @@
8787
</LinearLayout>
8888

8989
<!-- MAIN PANEL: shown after setup -->
90-
<LinearLayout
90+
<FrameLayout
9191
android:id="@+id/mainPanel"
9292
android:layout_width="match_parent"
9393
android:layout_height="match_parent"
94-
android:orientation="vertical"
95-
android:gravity="center"
96-
android:padding="12dp"
94+
android:padding="8dp"
9795
android:visibility="gone">
9896

9997
<TextView
10098
android:id="@+id/statusText"
101-
android:layout_width="match_parent"
99+
android:layout_width="140dp"
102100
android:layout_height="wrap_content"
101+
android:layout_gravity="top|center_horizontal"
102+
android:layout_marginTop="2dp"
103103
android:text="Starting…"
104104
android:textColor="#D4A5E9"
105-
android:textSize="12sp"
105+
android:textSize="11sp"
106106
android:gravity="center"
107-
android:maxLines="2"
107+
android:maxLines="1"
108108
android:ellipsize="end"
109109
android:includeFontPadding="false"
110-
android:paddingStart="10dp"
111-
android:paddingEnd="10dp"
112-
android:paddingTop="6dp"
113-
android:paddingBottom="6dp"
114-
android:background="@drawable/live_text_bg"
115-
android:layout_marginBottom="8dp" />
116-
117-
<FrameLayout
118-
android:id="@+id/avatarContainer"
119-
android:layout_width="124dp"
120-
android:layout_height="124dp"
121-
android:layout_marginBottom="12dp">
122-
123-
<TextView
124-
android:id="@+id/avatarFace"
125-
android:layout_width="match_parent"
126-
android:layout_height="match_parent"
127-
android:gravity="center"
128-
android:text="🐜"
129-
android:textColor="#D4A5E9"
130-
android:textSize="72sp" />
131-
132-
<TextView
133-
android:id="@+id/actionIndicator"
134-
android:layout_width="32dp"
135-
android:layout_height="32dp"
136-
android:layout_gravity="end|top"
137-
android:layout_marginTop="14dp"
138-
android:layout_marginEnd="4dp"
139-
android:gravity="center"
140-
android:text=""
141-
android:textColor="#D4A5E9"
142-
android:textSize="24sp"
143-
android:includeFontPadding="false" />
144-
</FrameLayout>
145-
146-
<FrameLayout
147-
android:layout_width="60dp"
148-
android:layout_height="60dp">
149-
150-
<com.google.android.material.progressindicator.CircularProgressIndicator
151-
android:id="@+id/autoListenCountdown"
152-
android:layout_width="60dp"
153-
android:layout_height="60dp"
154-
android:layout_gravity="center"
155-
android:max="100"
156-
android:visibility="gone"
157-
app:indicatorColor="#D4A5E9"
158-
app:indicatorSize="60dp"
159-
app:trackColor="#00000000"
160-
app:trackThickness="3dp" />
161-
162-
<androidx.appcompat.widget.AppCompatButton
163-
android:id="@+id/fab"
164-
android:layout_width="42dp"
165-
android:layout_height="42dp"
166-
android:layout_gravity="center"
167-
android:contentDescription="Tap to talk"
168-
android:background="@drawable/action_bubble_bg"
169-
android:elevation="0dp"
170-
android:gravity="center"
171-
android:includeFontPadding="false"
172-
android:minHeight="0dp"
173-
android:minWidth="0dp"
174-
android:padding="0dp"
175-
android:stateListAnimator="@null"
176-
android:text=""
177-
android:textAllCaps="false"
178-
android:textColor="#0A0A0F"
179-
android:textSize="18sp"
180-
android:textStyle="bold" />
181-
</FrameLayout>
110+
android:paddingStart="8dp"
111+
android:paddingEnd="8dp"
112+
android:paddingTop="5dp"
113+
android:paddingBottom="5dp"
114+
android:minHeight="24dp"
115+
android:background="@drawable/live_text_bg" />
116+
117+
<LinearLayout
118+
android:layout_width="match_parent"
119+
android:layout_height="match_parent"
120+
android:gravity="center"
121+
android:orientation="vertical">
122+
123+
<FrameLayout
124+
android:id="@+id/avatarContainer"
125+
android:layout_width="120dp"
126+
android:layout_height="120dp"
127+
android:layout_marginBottom="10dp">
128+
129+
<TextView
130+
android:id="@+id/avatarFace"
131+
android:layout_width="match_parent"
132+
android:layout_height="match_parent"
133+
android:gravity="center"
134+
android:text="🐜"
135+
android:textColor="#D4A5E9"
136+
android:textSize="68sp" />
137+
138+
<TextView
139+
android:id="@+id/actionIndicator"
140+
android:layout_width="30dp"
141+
android:layout_height="30dp"
142+
android:layout_gravity="end|top"
143+
android:layout_marginTop="14dp"
144+
android:layout_marginEnd="4dp"
145+
android:gravity="center"
146+
android:text=""
147+
android:textColor="#D4A5E9"
148+
android:textSize="22sp"
149+
android:includeFontPadding="false" />
150+
</FrameLayout>
151+
152+
<FrameLayout
153+
android:layout_width="58dp"
154+
android:layout_height="58dp">
155+
156+
<com.google.android.material.progressindicator.CircularProgressIndicator
157+
android:id="@+id/autoListenCountdown"
158+
android:layout_width="58dp"
159+
android:layout_height="58dp"
160+
android:layout_gravity="center"
161+
android:max="100"
162+
android:visibility="gone"
163+
app:indicatorColor="#D4A5E9"
164+
app:indicatorSize="58dp"
165+
app:trackColor="#00000000"
166+
app:trackThickness="3dp" />
167+
168+
<androidx.appcompat.widget.AppCompatButton
169+
android:id="@+id/fab"
170+
android:layout_width="42dp"
171+
android:layout_height="42dp"
172+
android:layout_gravity="center"
173+
android:contentDescription="Tap to talk"
174+
android:background="@drawable/action_bubble_bg"
175+
android:elevation="0dp"
176+
android:gravity="center"
177+
android:includeFontPadding="false"
178+
android:minHeight="0dp"
179+
android:minWidth="0dp"
180+
android:padding="0dp"
181+
android:stateListAnimator="@null"
182+
android:text=""
183+
android:textAllCaps="false"
184+
android:textColor="#0A0A0F"
185+
android:textSize="18sp"
186+
android:textStyle="bold" />
187+
</FrameLayout>
188+
</LinearLayout>
182189

183190
<!-- Legacy bound views kept hidden for compatibility -->
184191
<TextView
@@ -201,6 +208,6 @@
201208
android:layout_height="1dp"
202209
android:visibility="gone" />
203210

204-
</LinearLayout>
211+
</FrameLayout>
205212

206213
</androidx.wear.widget.BoxInsetLayout>

assets/screenshots/watch-01.png

8.56 KB
Loading

assets/screenshots/watch-02.png

7.59 KB
Loading

assets/screenshots/watch-03.png

7.58 KB
Loading

assets/screenshots/watch-04.png

9.62 KB
Loading

phone/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId = "com.thinkoff.clawwatch" // same as watch — Play Store pairing
1212
minSdk = 26 // Android 8.0+
1313
targetSdk = 34
14-
versionCode = 1
15-
versionName = "0.1.0"
14+
versionCode = 2
15+
versionName = "1.0.0"
1616
}
1717

1818
buildTypes {

0 commit comments

Comments
 (0)