Cache reimplementation
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { pieceCache } from "@/cache";
|
||||
import { denormalizePiece, pieceCache } from "@/cache";
|
||||
import { client } from "@/client";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||
import { useCache } from "@/hooks/useCache";
|
||||
import { useLoading } from "@/hooks/useLoading";
|
||||
import { Updater } from "@/hooks/useStore";
|
||||
import { authors, created, DEBOUNCE, modified, SAVE_DELAY } from "@/snippets";
|
||||
@@ -12,8 +13,8 @@ import clsx from "clsx";
|
||||
import { PieceId } from "common";
|
||||
import * as Body from "common/Body";
|
||||
import { getMediaTypeForFilename } from "common/MediaType";
|
||||
import { Array, Cause, Effect, Fiber, Iterable, Match, Option, Order, pipe, Scope, SortedMap } from "effect";
|
||||
import { Import, Loader2, Plus, UploadCloud } from "lucide-react";
|
||||
import { Array, Cause, Effect, Fiber, Iterable, Match, Option, Order, pipe, Predicate, Scope, SortedMap } from "effect";
|
||||
import { Import, Loader2, Plus } from "lucide-react";
|
||||
import { DragEventHandler, FormEventHandler, useId, useRef, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
|
||||
@@ -119,7 +120,7 @@ namespace PieceRow {
|
||||
|
||||
function PieceRow(props: PieceRow.Props) {
|
||||
|
||||
const { isLoading, error, data: piece } = useLoading(Effect.uninterruptible(pieceCache.get(props.pieceId)), [props.pieceId]);
|
||||
const { isLoading, error, data: piece } = useCache(pieceCache, props.pieceId);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -188,12 +189,16 @@ function AddPieceDialogContent() {
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
const { pieceId } = yield* client.createPiece({
|
||||
name,
|
||||
composer: composer.length > 0 ? Option.some(composer) : Option.none(),
|
||||
lyricist: lyricist.length > 0 ? Option.some(lyricist) : Option.none(),
|
||||
arranger: arranger.length > 0 ? Option.some(arranger) : Option.none(),
|
||||
});
|
||||
const { pieceId } = yield* pipe(
|
||||
client.createPiece({
|
||||
name,
|
||||
composer: composer.length > 0 ? Option.some(composer) : Option.none(),
|
||||
lyricist: lyricist.length > 0 ? Option.some(lyricist) : Option.none(),
|
||||
arranger: arranger.length > 0 ? Option.some(arranger) : Option.none(),
|
||||
}),
|
||||
Effect.flatMap(denormalizePiece),
|
||||
Effect.tap((piece) => Effect.sync(() => pieceCache.setFulfilledSucceed(piece.pieceId, piece))),
|
||||
);
|
||||
|
||||
navigate(pieceId);
|
||||
}));
|
||||
@@ -262,7 +267,7 @@ function ImportPiecesDialogContent(props: ImportPiecesDialogContent.Props) {
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const [attachments, setAttachments] = useState<SortedMap.SortedMap<string, readonly File[]>>(() => SortedMap.empty(Order.string));
|
||||
const [files, setFiles] = useState<SortedMap.SortedMap<string, readonly File[]>>(() => SortedMap.empty(Order.string));
|
||||
|
||||
const onDragOver: DragEventHandler<HTMLElement> = (e) => {
|
||||
e.preventDefault();
|
||||
@@ -272,7 +277,7 @@ function ImportPiecesDialogContent(props: ImportPiecesDialogContent.Props) {
|
||||
const onDrop: DragEventHandler<HTMLElement> = (e) => Effect.gen(function* () {
|
||||
e.preventDefault();
|
||||
|
||||
setAttachments((value) => {
|
||||
setFiles((value) => {
|
||||
for (const file of e.dataTransfer.files) {
|
||||
const mediaType = getMediaTypeForFilename(file.name);
|
||||
if (mediaType === undefined) {
|
||||
@@ -314,18 +319,20 @@ function ImportPiecesDialogContent(props: ImportPiecesDialogContent.Props) {
|
||||
setIsLoading(true);
|
||||
|
||||
yield* pipe(
|
||||
attachments,
|
||||
Iterable.map(([name, attachments]) => Effect.gen(function* () {
|
||||
files,
|
||||
Iterable.map(([name, files]) => Effect.gen(function* () {
|
||||
|
||||
const { pieceId } = yield* client.createPiece({
|
||||
name,
|
||||
composer: Option.none(),
|
||||
arranger: Option.none(),
|
||||
lyricist: Option.none(),
|
||||
});
|
||||
const piece = yield* pipe(
|
||||
client.createPiece({
|
||||
name,
|
||||
composer: Option.none(),
|
||||
arranger: Option.none(),
|
||||
lyricist: Option.none(),
|
||||
}),
|
||||
);
|
||||
|
||||
yield* pipe(
|
||||
attachments,
|
||||
const attachments = yield* pipe(
|
||||
files,
|
||||
Array.map((file) => Effect.gen(function* () {
|
||||
const mediaType = getMediaTypeForFilename(file.name);
|
||||
if (mediaType === undefined) {
|
||||
@@ -335,14 +342,23 @@ function ImportPiecesDialogContent(props: ImportPiecesDialogContent.Props) {
|
||||
// NOTE Apparently, file.bytes is not a thing in this context
|
||||
const data = new Uint8Array(yield* Body.arrayBuffer(file));
|
||||
|
||||
yield* client.createAttachment({
|
||||
pieceId,
|
||||
const attachment = yield* client.createAttachment({
|
||||
pieceId: piece.pieceId,
|
||||
data,
|
||||
filename: file.name,
|
||||
mediaType,
|
||||
});
|
||||
|
||||
return attachment;
|
||||
})),
|
||||
Effect.allWith({ concurrency: "unbounded" }),
|
||||
Effect.map(Array.filter(Predicate.isNotUndefined)),
|
||||
);
|
||||
|
||||
yield* pipe(
|
||||
{ ...piece, attachments },
|
||||
denormalizePiece,
|
||||
Effect.tap((piece) => Effect.sync(() => pieceCache.setFulfilledSucceed(piece.pieceId, piece))),
|
||||
);
|
||||
})),
|
||||
Effect.allWith({ concurrency: "unbounded" }),
|
||||
@@ -359,7 +375,7 @@ function ImportPiecesDialogContent(props: ImportPiecesDialogContent.Props) {
|
||||
<DialogTitle>Importuj utwory</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-4 py-4">
|
||||
{SortedMap.size(attachments) > 0 && (
|
||||
{SortedMap.size(files) > 0 && (
|
||||
<div className="max-h-[50vh] overflow-y-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
@@ -370,7 +386,7 @@ function ImportPiecesDialogContent(props: ImportPiecesDialogContent.Props) {
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{pipe(
|
||||
attachments,
|
||||
files,
|
||||
SortedMap.entries,
|
||||
Iterable.map(([name, files]) => (
|
||||
<TableRow key={name}>
|
||||
|
||||
Reference in New Issue
Block a user