diff --git a/README.md b/README.md
index bbd3e2b..ecc0b78 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@ The app demonstrates:
- embedding `ConvoKitConversation` from `app.convokit:convokit-android-ui` in an Android Views application with `ComposeView`;
- delegating message history, sending, editing and deleting your own messages, quoted replies and jump-to-message, media rendering, typing and read receipts to the reusable UI library;
- calling the 0.9.0 core surface directly from the host: sending with `replyToMessageId`, resolving a whole page of quoted rows with one `getReplyPreviews` call, centring a window with `getMessageContext`, and telling the coded `MESSAGE_NOT_FOUND` and `CONVERSATION_NOT_FOUND` answers apart;
+- calling the reaction core API directly: add/remove one exact `ππ½`, read a batched summary, and load the first page of reactors, while the embedded UI handles its own reaction controls;
- creating an adapter after each successful login and disposing the old conversation before disconnecting or switching users.
The sample no longer maintains a second message renderer, composer, or raw
@@ -36,9 +37,9 @@ The host handles system-bar, display-cutout and keyboard insets before embedding
Compose, so padding is not applied twice. Local host tests use Robolectric and
synthetic insets; they do not prove hosted authorization or physical-device chat.
-### Published 0.9.0 SDKs
+### Published 0.10.0 SDKs
-The example consumes the published 0.9.0 core and UI from maven.convokit.app.
+The example consumes the published 0.10.0 core and UI from maven.convokit.app.
The embedded room acknowledges a concrete message for precise read positions,
defers acknowledgements while the host is hidden, correlates pending sends
with live/history confirmations before HTTP returns, and sends the caller's
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 1a56b94..e2815ac 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -40,8 +40,8 @@ android {
}
dependencies {
- implementation("app.convokit:convokit-android:0.9.0")
- implementation("app.convokit:convokit-android-ui:0.9.0")
+ implementation("app.convokit:convokit-android:0.10.0")
+ implementation("app.convokit:convokit-android-ui:0.10.0")
implementation("androidx.activity:activity-ktx:1.10.1")
implementation("androidx.appcompat:appcompat:1.7.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.1")
diff --git a/app/src/main/kotlin/app/convokit/example/MainActivity.kt b/app/src/main/kotlin/app/convokit/example/MainActivity.kt
index 7e1776d..1220e41 100644
--- a/app/src/main/kotlin/app/convokit/example/MainActivity.kt
+++ b/app/src/main/kotlin/app/convokit/example/MainActivity.kt
@@ -72,6 +72,7 @@ class MainActivity : AppCompatActivity() {
onBackPressedDispatcher.addCallback(this, roomBack)
binding.joinButton.setOnClickListener { joinRoom() }
binding.replyDemoButton.setOnClickListener { runReplyDemo() }
+ binding.reactionDemoButton.setOnClickListener { runReactionDemo() }
}
private fun joinRoom() {
@@ -106,6 +107,7 @@ class MainActivity : AppCompatActivity() {
joinedRoomId = roomId
binding.replyDemoStatus.setText(R.string.reply_demo_hint)
binding.replyDemoButton.isEnabled = true
+ binding.reactionDemoButton.isEnabled = true
roomBack.isEnabled = true
} catch (cause: Throwable) {
withContext(NonCancellable) { convoKit.disconnectUser() }
@@ -124,6 +126,7 @@ class MainActivity : AppCompatActivity() {
binding.chatContent.disposeComposition()
binding.room.visibility = View.GONE
binding.replyDemoButton.isEnabled = false
+ binding.reactionDemoButton.isEnabled = false
joinedRoomId = null
binding.joinForm.visibility = View.VISIBLE
binding.status.text = getString(R.string.disconnecting)
@@ -160,6 +163,38 @@ class MainActivity : AppCompatActivity() {
}
}
+ /** Direct core API tour. The Compose conversation handles its own picker and chips. */
+ private fun runReactionDemo() {
+ val roomId = joinedRoomId ?: return
+ binding.reactionDemoButton.isEnabled = false
+ binding.reactionDemoStatus.setText(R.string.reaction_demo_running)
+ lifecycleScope.launch {
+ try {
+ val newest = convoKit.getMessages(roomId, limit = 1).firstOrNull()
+ val report = if (newest == null) {
+ getString(R.string.reaction_demo_empty)
+ } else {
+ val emoji = "ππ½" // Preserve the exact Unicode sequence, including its skin tone.
+ val added = convoKit.addReaction(newest.id, emoji)
+ val summary = convoKit.getReactionSummaries(roomId, listOf(newest.id))
+ .firstOrNull()?.reactions?.find { it.emoji == emoji }
+ val reactors = convoKit.listReactionUsers(newest.id, emoji, limit = 10)
+ val removed = convoKit.removeReaction(newest.id, emoji)
+ "Added $emoji to ${newest.id}: changed=${added.changed}; " +
+ "count=${summary?.count ?: 0}, reactedByMe=${summary?.reactedByMe ?: false}; " +
+ "reactors on first page=${reactors.data.size}, next page=${reactors.nextCursor != null}; " +
+ "removed: changed=${removed.changed}."
+ }
+ if (joinedRoomId == roomId) binding.reactionDemoStatus.text = report
+ } catch (cause: Throwable) {
+ if (cause is CancellationException) throw cause
+ if (joinedRoomId == roomId) binding.reactionDemoStatus.setText(R.string.reaction_demo_failed)
+ } finally {
+ binding.reactionDemoButton.isEnabled = joinedRoomId != null
+ }
+ }
+ }
+
private suspend fun issueUserToken(appUserId: String): String {
val response = postJson(
"${BuildConfig.DEMO_BACKEND_URL}/api/auth/token".toHttpUrl(),
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 1621878..6b39680 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -107,6 +107,22 @@
android:textColor="@color/convokit_text"
android:textSize="13sp" />
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2a6a2d3..2e08a4d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -16,4 +16,9 @@
Quotes the newest message, resolves every quoted row on the page in one call, centres a window on the quote and shows the two 404s a host must tell apart. Running it sends one message to this room.
Running the quoted-reply demoβ¦
The quoted-reply demo could not reach ConvoKit. Check your connection and try again.
+ Run the reaction API demo
+ Adds and removes one ππ½ on the newest message, reads its batched summary, and pages the reactor list. The conversation above handles reactions automatically.
+ Running the reaction API demoβ¦
+ This room has no message to react to yet.
+ The reaction API demo could not reach ConvoKit. Check access and try again.