feat: order streams by last child creation
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useEffectEvent, useRef, useState } from "react";
|
||||
import { useAuthStore } from "@/stores/auth-store";
|
||||
import { useCreateParticle, useCreateStreamParticle } from "@/hooks/use-create-particle";
|
||||
import { useRecordingMode } from "@/hooks/use-recording-mode";
|
||||
import { useRecorder } from "@/features/compose/use-recorder";
|
||||
import { particlePath, toFirestoreChildrenPath } from "@/lib/particle-path";
|
||||
import { particlePath } from "@/lib/particle-path";
|
||||
import type { ParticlePath } from "@/lib/particle-path";
|
||||
import { RecordingOverlay } from "@/features/compose/recording-overlay";
|
||||
import { TextComposeStep } from "@/features/compose/text-compose-step";
|
||||
@@ -14,6 +14,7 @@ type ComposeStep = "idle" | "recording" | "reviewing" | "typing" | "configuring"
|
||||
|
||||
interface ComposeOverlayProps {
|
||||
networkId: string;
|
||||
// Optional target path for reply mode. If not provided, compose creates a new stream.
|
||||
targetPath?: ParticlePath;
|
||||
onActiveChange?: (active: boolean) => void;
|
||||
}
|
||||
@@ -101,12 +102,12 @@ export function ComposeOverlay({
|
||||
);
|
||||
|
||||
const createChildParticle = useCallback(
|
||||
async (collectionPath: string) => {
|
||||
async (path: ParticlePath) => {
|
||||
if (!userEmail) return;
|
||||
|
||||
if (textContent.trim()) {
|
||||
await createParticle.mutateAsync({
|
||||
collectionPath,
|
||||
path,
|
||||
type: "text",
|
||||
properties: { content: textContent },
|
||||
createdByEmail: userEmail,
|
||||
@@ -118,7 +119,7 @@ export function ComposeOverlay({
|
||||
);
|
||||
|
||||
await createParticle.mutateAsync({
|
||||
collectionPath,
|
||||
path,
|
||||
type: "media",
|
||||
properties: {
|
||||
object_id,
|
||||
@@ -142,25 +143,19 @@ export function ComposeOverlay({
|
||||
);
|
||||
|
||||
// Reply mode: create particle directly under targetPath
|
||||
const submitReply = useCallback(async () => {
|
||||
const onSubmitReply = useEffectEvent(async () => {
|
||||
if (!targetPath || !userEmail) return;
|
||||
const collectionPath = toFirestoreChildrenPath(targetPath);
|
||||
await createChildParticle(collectionPath);
|
||||
await createChildParticle(targetPath);
|
||||
cancel();
|
||||
}, [targetPath, userEmail, createChildParticle, cancel]);
|
||||
|
||||
const submitReplyRef = useRef(submitReply);
|
||||
submitReplyRef.current = submitReply;
|
||||
});
|
||||
|
||||
// New stream mode: create stream + first child
|
||||
const handleStreamSubmit = useCallback(
|
||||
async (streamName: string, visibleTo: string[]) => {
|
||||
if (!userEmail) return;
|
||||
|
||||
const collectionPath = toFirestoreChildrenPath(particlePath(networkId));
|
||||
|
||||
const streamId = await createStream.mutateAsync({
|
||||
collectionPath,
|
||||
networkId,
|
||||
properties: {
|
||||
name: streamName,
|
||||
status: "open",
|
||||
@@ -169,11 +164,9 @@ export function ComposeOverlay({
|
||||
visibleTo,
|
||||
});
|
||||
|
||||
const streamChildrenPath = toFirestoreChildrenPath(
|
||||
particlePath(networkId, [streamId]),
|
||||
);
|
||||
|
||||
const streamChildrenPath = particlePath(networkId, [streamId]);
|
||||
await createChildParticle(streamChildrenPath);
|
||||
|
||||
cancel();
|
||||
},
|
||||
[networkId, userEmail, createParticle, createChildParticle, cancel],
|
||||
@@ -226,7 +219,7 @@ export function ComposeOverlay({
|
||||
} else if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
if (targetPath) {
|
||||
submitReplyRef.current();
|
||||
onSubmitReply();
|
||||
} else {
|
||||
setStep("configuring");
|
||||
}
|
||||
@@ -256,7 +249,7 @@ export function ComposeOverlay({
|
||||
if (step === "idle") return null;
|
||||
|
||||
const handleTextAdvance = targetPath
|
||||
? submitReply
|
||||
? onSubmitReply
|
||||
: () => setStep("configuring");
|
||||
|
||||
return (
|
||||
|
||||
@@ -204,7 +204,7 @@ interface ParticleListViewProps {
|
||||
* List of stream particles for a container (network root, folder, etc.).
|
||||
*/
|
||||
export function ParticleListView({ path }: ParticleListViewProps) {
|
||||
const { children, isLoading } = useLiveParticleChildren(path);
|
||||
const { children, isLoading } = useLiveParticleChildren(path, "last_child_created_at", "desc");
|
||||
const { networkId } = parseParticlePath(path);
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ interface StreamViewProps {
|
||||
export function StreamView({ path, streamParticle }: StreamViewProps) {
|
||||
const { networkId } = parseParticlePath(path);
|
||||
const navigate = useNavigate();
|
||||
const { children } = useLiveParticleChildren(path);
|
||||
const { children } = useLiveParticleChildren(path, "created_at", "asc");
|
||||
|
||||
const [state, dispatch] = useReducer(playbackReducer, initialState);
|
||||
const [composeActive, setComposeActive] = useState(false);
|
||||
|
||||
Reference in New Issue
Block a user