Repository navigation
fix(mobile): keep Live Activity status aligned with the inbox #26261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jakeleventhal
wants to merge
21
commits into
pingdotgg:main
Choose a base branch
from
jakeleventhal:fix/live-activity-desktop-parity-upstream
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,151
−328
Open
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
2e3a6eb
fix(mobile): keep Live Activity status aligned with the inbox
jakeleventhal 25ad42e
fix(mobile): handle replay races and terminal activity headers
jakeleventhal 56552f5
fix(mobile): preserve pending activity and off-card alerts
jakeleventhal 89473ad
fix(mobile): preserve approval alerts during off-card updates
jakeleventhal 4be6296
fix(mobile): acknowledge replayed threads without consuming other alerts
jakeleventhal cb5649b
test(mobile): suppress alerts in retained activity lifecycle case
jakeleventhal b408f9d
fix(mobile): retain unacknowledged snooze wakes in agent activity
jakeleventhal 8df653b
fix(mobile): let read timestamps shrink on narrow activity cards
jakeleventhal de60a08
fix(mobile): link activity to the first visible attention row
jakeleventhal be2bcc0
test(mobile): cover minimal activity glyph for snooze wakes
jakeleventhal a2c48bd
merge: bring main into live activity parity
maria-rcks ae56092
fix(relay): preserve live activity transitions during replay
maria-rcks 7619036
fix(web): acknowledge snooze wakes when viewing threads
maria-rcks 1dce965
merge: bring main into live activity parity
juliusmarminge dd538b2
fix(mobile): finish Live Activity parity on current main
juliusmarminge 5a217cd
fix(relay): keep Android Live Updates compatible and bound retained rows
juliusmarminge ddcde3e
fix(relay): end iOS cards on read and narrow startup result replays
juliusmarminge 33bfa96
Merge remote-tracking branch 'origin/main' into fix/live-activity-des…
juliusmarminge 9c3f19d
fix(server): catch up results finished since startup after publishing…
juliusmarminge f6b3dba
fix(relay): match inbox snoozes, keep Android results, alert settled …
juliusmarminge cc1757b
fix(relay): keep settled live work, group off-card results, catch up …
juliusmarminge File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
...ons/android/src/test/java/expo/modules/t3agentnotifications/AgentActivityLifecycleTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| package expo.modules.t3agentnotifications | ||
|
|
||
| import android.app.Activity | ||
| import android.app.AlarmManager | ||
| import android.app.Application | ||
| import android.app.Notification | ||
| import android.app.NotificationManager | ||
| import android.content.ComponentName | ||
| import android.content.Intent | ||
| import android.content.IntentFilter | ||
| import android.os.Build | ||
| import androidx.lifecycle.Lifecycle | ||
| import androidx.lifecycle.LifecycleRegistry | ||
| import androidx.lifecycle.ProcessLifecycleOwner | ||
| import org.junit.Assert.assertEquals | ||
| import org.junit.Assert.assertTrue | ||
| import org.junit.Before | ||
| import org.junit.Test | ||
| import org.junit.runner.RunWith | ||
| import org.robolectric.RobolectricTestRunner | ||
| import org.robolectric.RuntimeEnvironment | ||
| import org.robolectric.Shadows.shadowOf | ||
| import org.robolectric.annotation.Config | ||
|
|
||
| @RunWith(RobolectricTestRunner::class) | ||
| @Config(sdk = [24, 26, 33, 36], manifest = Config.NONE) | ||
| class AgentActivityLifecycleTest { | ||
| private lateinit var context: Application | ||
| private lateinit var manager: NotificationManager | ||
| private lateinit var lifecycle: LifecycleRegistry | ||
|
|
||
| @Before | ||
| fun setUp() { | ||
| context = RuntimeEnvironment.getApplication() | ||
| manager = context.getSystemService(NotificationManager::class.java) | ||
| shadowOf(manager).setNotificationsEnabled(true) | ||
| lifecycle = ProcessLifecycleOwner.get().lifecycle as LifecycleRegistry | ||
| lifecycle.currentState = Lifecycle.State.CREATED | ||
|
|
||
| val launcher = ComponentName(context, Activity::class.java) | ||
| shadowOf(context.packageManager).addActivityIfNotPresent(launcher) | ||
| shadowOf(context.packageManager).addIntentFilterForActivity( | ||
| launcher, | ||
| IntentFilter(Intent.ACTION_MAIN).apply { | ||
| addCategory(Intent.CATEGORY_LAUNCHER) | ||
| } | ||
| ) | ||
| AgentNotifications.clear(context) | ||
| AgentNotifications.configure(context, "device", "user", "t3code-dev", true) | ||
| AgentNotifications.setThreadOnScreen("/threads/environment/thread") | ||
| } | ||
|
|
||
| private fun update(alertId: String, active: Boolean) = mapOf( | ||
| "device_id" to "device", | ||
| "user_id" to "user", | ||
| "updated_at" to System.currentTimeMillis().toString(), | ||
| "active" to active.toString(), | ||
| "activity_title" to "1 active agent", | ||
| "activity_body" to "Test thread · Working", | ||
| "activity_path" to "/threads/environment/thread", | ||
| "alert_id" to alertId, | ||
| "alert_group" to "environment/thread", | ||
| "alert_title" to "Test thread", | ||
| "alert_body" to "Done: Test project", | ||
| "alert_path" to "/threads/environment/thread", | ||
| ) | ||
|
|
||
| @Test | ||
| fun retainedUnreadResultHasNoTimeoutAndReadingItClearsTheCard() { | ||
| lifecycle.currentState = Lifecycle.State.RESUMED | ||
| AgentNotifications.receive( | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
| context, | ||
| update("done", true) + mapOf( | ||
| "activity_phase" to "completed", | ||
| "activity_expires_at" to "0", | ||
| ) | ||
| ) | ||
| val card = manager.activeNotifications.single().notification | ||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) assertEquals(0L, card.timeoutAfter) | ||
| assertTrue( | ||
| shadowOf(context.getSystemService(AlarmManager::class.java)).scheduledAlarms.isEmpty() | ||
| ) | ||
| AgentNotifications.expire(context, System.currentTimeMillis() + 24 * 60 * 60 * 1000L) | ||
| assertEquals(1, manager.activeNotifications.size) | ||
| AgentNotifications.receive( | ||
| context, | ||
| update("done-read", false) + mapOf( | ||
| "activity_expires_at" to "0", | ||
| ) | ||
| ) | ||
| assertEquals(0, manager.activeNotifications.size) | ||
| } | ||
|
|
||
| @Test | ||
| fun waitingThreadsShowTheirCountInsteadOfZeroWorking() { | ||
| lifecycle.currentState = Lifecycle.State.RESUMED | ||
| val data = update("waiting-only", true) + mapOf( | ||
| "activity_line_0" to "Input\tChoose a model\tProject", | ||
| "activity_line_1" to "Input\tChoose an icon\tProject", | ||
| "activity_phase" to "waiting_for_input", | ||
| "activity_active_count" to "2", | ||
| "activity_attention_count" to "2", | ||
| "activity_working_count" to "0", | ||
| "activity_total_count" to "2", | ||
| ) | ||
| AgentNotifications.receive(context, data) | ||
| val card = manager.activeNotifications.single().notification | ||
| assertEquals("Project · 2 threads", card.extras.getString(Notification.EXTRA_SUB_TEXT)) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Medium
t3code/apps/mobile/modules/t3-agent-notifications/android/src/main/java/expo/modules/t3agentnotifications/AgentNotifications.kt
Line 276 in dd538b2
A later retained completion on the same thread is canceled even when no alert covered it, because
singleTerminal()produces the samepath\ncompleted\n0key andcoveredTerminalis never invalidated. Include a per-completion identifier in the coverage key or clear coverage when a new run starts.🤖 Copy this AI Prompt to have your agent fix this: