@reffuse/extension-query 0.1.4 #15
@@ -7,15 +7,8 @@ import { Chunk, Context, Effect, identity, Layer, ParseResult, Ref, Schema, Stre
|
|||||||
|
|
||||||
export class TodosState extends Context.Tag("TodosState")<TodosState, {
|
export class TodosState extends Context.Tag("TodosState")<TodosState, {
|
||||||
readonly todos: SubscriptionRef.SubscriptionRef<Chunk.Chunk<Todo.Todo>>
|
readonly todos: SubscriptionRef.SubscriptionRef<Chunk.Chunk<Todo.Todo>>
|
||||||
|
|
||||||
readonly load: Effect.Effect<void, PlatformError | ParseResult.ParseError>
|
readonly load: Effect.Effect<void, PlatformError | ParseResult.ParseError>
|
||||||
readonly save: Effect.Effect<void, PlatformError | ParseResult.ParseError>
|
readonly save: Effect.Effect<void, PlatformError | ParseResult.ParseError>
|
||||||
|
|
||||||
readonly prepend: (todo: Todo.Todo) => Effect.Effect<void>
|
|
||||||
readonly replace: (index: number, todo: Todo.Todo) => Effect.Effect<void>
|
|
||||||
readonly remove: (index: number) => Effect.Effect<void>
|
|
||||||
// readonly moveUp: (index: number) => Effect.Effect<void, Cause.NoSuchElementException>
|
|
||||||
// readonly moveDown: (index: number) => Effect.Effect<void, Cause.NoSuchElementException>
|
|
||||||
}>() {}
|
}>() {}
|
||||||
|
|
||||||
|
|
||||||
@@ -41,30 +34,11 @@ export const make = (key: string) => Layer.effect(TodosState, Effect.gen(functio
|
|||||||
)
|
)
|
||||||
|
|
||||||
const todos = yield* SubscriptionRef.make(yield* readFromLocalStorage)
|
const todos = yield* SubscriptionRef.make(yield* readFromLocalStorage)
|
||||||
|
|
||||||
const load = Effect.flatMap(readFromLocalStorage, v => Ref.set(todos, v))
|
const load = Effect.flatMap(readFromLocalStorage, v => Ref.set(todos, v))
|
||||||
const save = Effect.flatMap(todos, writeToLocalStorage)
|
const save = Effect.flatMap(todos, writeToLocalStorage)
|
||||||
|
|
||||||
const prepend = (todo: Todo.Todo) => Ref.update(todos, Chunk.prepend(todo))
|
|
||||||
const replace = (index: number, todo: Todo.Todo) => Ref.update(todos, Chunk.replace(index, todo))
|
|
||||||
const remove = (index: number) => Ref.update(todos, Chunk.remove(index))
|
|
||||||
|
|
||||||
// const moveUp = (index: number) => Effect.gen(function*() {
|
|
||||||
|
|
||||||
// })
|
|
||||||
|
|
||||||
// Sync changes with local storage
|
// Sync changes with local storage
|
||||||
yield* Effect.forkScoped(todos.changes.pipe(
|
yield* Effect.forkScoped(Stream.runForEach(todos.changes, writeToLocalStorage))
|
||||||
Stream.debounce("500 millis"),
|
|
||||||
Stream.runForEach(writeToLocalStorage),
|
|
||||||
))
|
|
||||||
|
|
||||||
return {
|
return { todos, load, save }
|
||||||
todos,
|
|
||||||
load,
|
|
||||||
save,
|
|
||||||
prepend,
|
|
||||||
replace,
|
|
||||||
remove,
|
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Todo } from "@/domain"
|
import { Todo } from "@/domain"
|
||||||
import { Box, Button, Card, Flex, TextArea } from "@radix-ui/themes"
|
import { Box, Button, Card, Flex, TextArea } from "@radix-ui/themes"
|
||||||
import { GetRandomValues, makeUuid4 } from "@typed/id"
|
import { GetRandomValues, makeUuid4 } from "@typed/id"
|
||||||
import { Effect, Option, Ref } from "effect"
|
import { Chunk, Effect, Option, Ref } from "effect"
|
||||||
import { R } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
import { TodosState } from "../services"
|
import { TodosState } from "../services"
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ export function VNewTodo() {
|
|||||||
const [content, setContent] = R.useRefState(R.useSubRefFromPath(todoRef, ["content"]))
|
const [content, setContent] = R.useRefState(R.useSubRefFromPath(todoRef, ["content"]))
|
||||||
|
|
||||||
const add = R.useCallbackSync(() => Effect.all([TodosState.TodosState, todoRef]).pipe(
|
const add = R.useCallbackSync(() => Effect.all([TodosState.TodosState, todoRef]).pipe(
|
||||||
Effect.flatMap(([state, todo]) => state.prepend(todo)),
|
Effect.flatMap(([state, todo]) => Ref.update(state.todos, Chunk.prepend(todo))),
|
||||||
Effect.andThen(createEmptyTodo),
|
Effect.andThen(createEmptyTodo),
|
||||||
Effect.flatMap(v => Ref.set(todoRef, v)),
|
Effect.flatMap(v => Ref.set(todoRef, v)),
|
||||||
), [todoRef])
|
), [todoRef])
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Todo } from "@/domain"
|
import { Todo } from "@/domain"
|
||||||
import { Box, Card, Flex, IconButton, TextArea } from "@radix-ui/themes"
|
import { Box, Card, Flex, IconButton, TextArea } from "@radix-ui/themes"
|
||||||
import { Effect, Ref, SubscriptionRef } from "effect"
|
import { Effect, Ref, Stream, SubscriptionRef } from "effect"
|
||||||
import { Delete } from "lucide-react"
|
import { Delete } from "lucide-react"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { R } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
@@ -14,7 +14,15 @@ export interface VTodoProps {
|
|||||||
export function VTodo({ todoRef, remove }: VTodoProps) {
|
export function VTodo({ todoRef, remove }: VTodoProps) {
|
||||||
|
|
||||||
const runSync = R.useRunSync()
|
const runSync = R.useRunSync()
|
||||||
const [todo] = R.useSubscribeRefs(todoRef)
|
|
||||||
|
const localTodoRef = R.useRef(() => todoRef)
|
||||||
|
const [content, setContent] = R.useRefState(R.useSubRefFromPath(localTodoRef, ["content"]))
|
||||||
|
|
||||||
|
R.useFork(() => localTodoRef.changes.pipe(
|
||||||
|
Stream.debounce("250 millis"),
|
||||||
|
Stream.runForEach(v => Ref.set(todoRef, v)),
|
||||||
|
), [localTodoRef])
|
||||||
|
|
||||||
const editorMode = useState(false)
|
const editorMode = useState(false)
|
||||||
|
|
||||||
|
|
||||||
@@ -23,13 +31,8 @@ export function VTodo({ todoRef, remove }: VTodoProps) {
|
|||||||
<Card>
|
<Card>
|
||||||
<Flex direction="column" align="stretch" gap="1">
|
<Flex direction="column" align="stretch" gap="1">
|
||||||
<TextArea
|
<TextArea
|
||||||
value={todo.content}
|
value={content}
|
||||||
onChange={e => runSync(
|
onChange={e => setContent(e.target.value)}
|
||||||
Ref.set(todoRef, Todo.Todo.make({
|
|
||||||
...todo,
|
|
||||||
content: e.target.value,
|
|
||||||
}, true))
|
|
||||||
)}
|
|
||||||
disabled={!editorMode}
|
disabled={!editorMode}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user