mobile: follow a just-sent particle when at the end of a stream (#226)

When the local user sends a particle while positioned on the last one in a
stream, advance playback to the newly created particle so they stay caught up
and the stream isn't left in an unseen state. If they're browsing earlier
particles, their position is left untouched.

The mobile reducer only auto-advanced on PARTICLE_ADDED when status was
already "ended", so sending while sitting on (but not finished with) the last
particle left it unseen. This threads an onParticleCreated callback from
ComposeDock's default send paths up to StreamView, which follows the particle
via goToParticle only when currentIndex is the last slot — mirroring desktop's
StreamView.handleParticleCreated.

Co-authored-by: Claude <[email protected]>
This commit was merged in pull request #226.
This commit is contained in:
Arjun Patel
2026-05-30 11:09:44 -07:00
committed by GitHub
co-authored by Claude
parent 0cd126818a
commit 7b000429e9
2 changed files with 42 additions and 5 deletions
+12 -2
View File
@@ -56,6 +56,13 @@ interface ComposeDockProps {
silentPresence?: boolean;
submitMedia?: (params: SubmitMediaParams) => Promise<void>;
submitText?: (content: string) => Promise<void>;
/**
* Called with the new particle's id right after it's created on the default
* send path. Not fired when `submitMedia`/`submitText` overrides are supplied,
* since those own the created particle themselves. Lets the stream follow a
* just-sent particle when the user was at the end.
*/
onParticleCreated?: (particleId: string) => void;
}
export function ComposeDock({
@@ -64,6 +71,7 @@ export function ComposeDock({
silentPresence = false,
submitMedia,
submitText: submitTextOverride,
onParticleCreated,
}: ComposeDockProps) {
const userId = useAuthStore((s) => s.user?.id);
@@ -147,7 +155,7 @@ export function ComposeDock({
source: "camera",
});
} else {
await uploadMediaParticle({
const particleId = await uploadMediaParticle({
networkId,
targetPath,
fileUri: captured.uri,
@@ -156,6 +164,7 @@ export function ComposeDock({
source: "camera",
createdByHumanId: userId,
});
onParticleCreated?.(particleId);
}
void Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
setUi({ kind: "idle" });
@@ -174,12 +183,13 @@ export function ComposeDock({
if (submitTextOverride) {
await submitTextOverride(content);
} else {
await createTextParticle({
const particleId = await createTextParticle({
networkId,
targetPath,
content,
createdByHumanId: userId,
});
onParticleCreated?.(particleId);
}
void Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
});