feat: stream list view and tasks (#279)
* first attempt at stream sidebar, tasks, and events * fix folder from root * cleanup folders and events, and condense changes * cleanup and add toggle for sidebar * cleanup * fix nits
This commit was merged in pull request #279.
This commit is contained in:
+41
-12
@@ -146,14 +146,21 @@ export const TextPropertiesSchema = z.object({
|
||||
});
|
||||
export type TextProperties = z.infer<typeof TextPropertiesSchema>;
|
||||
|
||||
export const QuestPropertiesSchema = z.object({
|
||||
export const ChecklistItemSchema = z.object({
|
||||
text: z.string(),
|
||||
done: z.boolean(),
|
||||
});
|
||||
export type ChecklistItem = z.infer<typeof ChecklistItemSchema>;
|
||||
|
||||
export const TaskPropertiesSchema = z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
status: z.string().optional(),
|
||||
notes: z.string().optional(),
|
||||
checklist: z.array(ChecklistItemSchema).optional(),
|
||||
// humanId
|
||||
assigned_to: z.string().optional(),
|
||||
done: z.boolean(),
|
||||
});
|
||||
export type QuestProperties = z.infer<typeof QuestPropertiesSchema>;
|
||||
export type TaskProperties = z.infer<typeof TaskPropertiesSchema>;
|
||||
|
||||
export const PaperPropertiesSchema = z.object({
|
||||
title: z.string(),
|
||||
@@ -194,7 +201,7 @@ export interface ParticlePropertiesMap {
|
||||
media: MediaProperties;
|
||||
file: FileProperties;
|
||||
text: TextProperties;
|
||||
quest: QuestProperties;
|
||||
task: TaskProperties;
|
||||
paper: PaperProperties;
|
||||
}
|
||||
|
||||
@@ -211,6 +218,9 @@ export const ParticleSchema = z.discriminatedUnion('type', [
|
||||
ParticleBaseSchema.extend({
|
||||
type: z.literal('stream'),
|
||||
properties: StreamPropertiesSchema,
|
||||
// Open/closed lifecycle. Optional because some streams were created while
|
||||
// the field was dropped — treat missing as 'open' (see isStreamOpen).
|
||||
status: z.enum(['open', 'closed']).optional(),
|
||||
// e.g. ["human:human_xxxx", "human:human_yyyy"] - visible only to Aron and John
|
||||
// e.g. ["network:xywx"] - visible to everyone in the network
|
||||
visible_to: z.array(z.string()),
|
||||
@@ -221,7 +231,6 @@ export const ParticleSchema = z.discriminatedUnion('type', [
|
||||
last_child_created_at: z.coerce.date().optional(),
|
||||
// Array of humanIds currently in the huddle (updated via LiveKit webhooks)
|
||||
huddle_active_participants: z.array(z.string()).optional(),
|
||||
status: z.enum(['open', 'closed']).optional(),
|
||||
}),
|
||||
ParticleBaseSchema.extend({
|
||||
type: z.literal('folder'),
|
||||
@@ -229,6 +238,9 @@ export const ParticleSchema = z.discriminatedUnion('type', [
|
||||
// e.g. ["human:human_xxxx", "human:human_yyyy"] - visible only to Aron and John
|
||||
// e.g. ["network:123"] - visible to everyone in the network
|
||||
visible_to: z.array(z.string()),
|
||||
// Set to created_at on creation, bumped when children are added — keeps
|
||||
// folders present in activity-ordered container queries.
|
||||
last_child_created_at: z.coerce.date().optional(),
|
||||
}),
|
||||
ParticleBaseSchema.extend({
|
||||
type: z.literal('media'),
|
||||
@@ -248,8 +260,9 @@ export const ParticleSchema = z.discriminatedUnion('type', [
|
||||
...TombstoneFields,
|
||||
}),
|
||||
ParticleBaseSchema.extend({
|
||||
type: z.literal('quest'),
|
||||
properties: QuestPropertiesSchema,
|
||||
type: z.literal('task'),
|
||||
properties: TaskPropertiesSchema,
|
||||
reactions: ReactionsSchema,
|
||||
...TombstoneFields,
|
||||
}),
|
||||
ParticleBaseSchema.extend({
|
||||
@@ -259,17 +272,28 @@ export const ParticleSchema = z.discriminatedUnion('type', [
|
||||
}),
|
||||
]);
|
||||
|
||||
export type Particle = z.infer<typeof ParticleSchema>;
|
||||
// Placeholder for docs whose `type` this client version doesn't recognize
|
||||
// (e.g. a newer client wrote a particle type we don't ship yet). The converter
|
||||
// maps them here instead of throwing, so they degrade to an "unsupported"
|
||||
// view rather than breaking the whole subscription.
|
||||
export const UnknownParticleSchema = ParticleBaseSchema.extend({
|
||||
type: z.literal('unknown'),
|
||||
raw_type: z.string(),
|
||||
});
|
||||
export type UnknownParticle = z.infer<typeof UnknownParticleSchema>;
|
||||
|
||||
export type ParticleType = Particle['type'];
|
||||
export type Particle = z.infer<typeof ParticleSchema> | UnknownParticle;
|
||||
|
||||
/** Particle types this client can read and write — excludes 'unknown'. */
|
||||
export type ParticleType = z.infer<typeof ParticleSchema>['type'];
|
||||
|
||||
/** Container types can have children subcollections */
|
||||
export const CONTAINER_TYPES: ReadonlySet<ParticleType> = new Set([
|
||||
export const CONTAINER_TYPES: ReadonlySet<Particle['type']> = new Set([
|
||||
'stream',
|
||||
'folder',
|
||||
]);
|
||||
|
||||
export function isContainerType(type: ParticleType): boolean {
|
||||
export function isContainerType(type: Particle['type']): boolean {
|
||||
return CONTAINER_TYPES.has(type);
|
||||
}
|
||||
|
||||
@@ -278,6 +302,11 @@ export function isParticleDeleted(particle: Particle): boolean {
|
||||
return 'deleted_at' in particle && particle.deleted_at != null;
|
||||
}
|
||||
|
||||
/** Missing status counts as open (streams created while the field was dropped). */
|
||||
export function isStreamOpen(stream: Extract<Particle, { type: 'stream' }>) {
|
||||
return stream.status !== 'closed';
|
||||
}
|
||||
|
||||
// --- LiveKit types ---
|
||||
|
||||
export const GetLivekitTokenResponseSchema = z.object({
|
||||
|
||||
Reference in New Issue
Block a user