Increase selection and recording functionality

- Added a button to each delta for selection
- Updated the `session` store to return the first session if the sessionId is not found
- Updated the `previousSession` store to return the session before the current one if it exists
- Updated the `docsNext` derived store to include the `selection` store
- Added an `if` statement for `files` in `+page.svelte`

[src/routes/projects/[projectId]/sessions/[sessionId]/+page.ts]
- Changed the import of `svelte/store` to include `writable`
- Changed the `session` store to return the first session if the sessionId is not found
- Changed the `previousSession` store to return the session before the current one if it exists
[src/routes/projects/[projectId]/sessions/[sessionId]/+page.svelte]
- Move the `Timeline` component import from `+page.svelte`
- Initialize `selection` store in `+page.svelte`
- Update `docsNext` derived store to include the `selection` store
- Add a button to each delta for selection
- Add an `if` statement for `files` in `+page.svelte`
- Delete `contentWithDeltasApplied` function from `+page.
This commit is contained in:
Kiril Videlov 2023-02-15 14:53:14 +01:00
parent 5697b204cb
commit c5c46e8a25
2 changed files with 50 additions and 68 deletions

View File

@ -1,9 +1,8 @@
<script lang="ts">
import { Doc } from "yjs";
import { Timeline, CodeViewer } from "$lib/components";
import { CodeViewer } from "$lib/components";
import { Operation } from "$lib/deltas";
import type { Delta } from "$lib/deltas";
import { derived, writable } from "svelte/store";
import { derived } from "svelte/store";
import type { PageData } from "./$types";
import SessionNav from "$lib/components/session/SessionNav.svelte";
import { toHumanReadableTime } from "$lib/time";
@ -15,21 +14,32 @@
$: nextSession = data.nextSession;
$: session = data.session;
$: deltas = data.deltas;
$: files = data.files;
const value = writable(new Date().getTime());
$: selection = {} as Record<string, Record<string, number>>;
const docs = derived(value, (value) =>
$: docsNext = derived([data.deltas], ([deltas]) =>
Object.fromEntries(
Object.entries($deltas).map(([filePath, deltas]) => {
Object.entries(deltas).map(([filePath, deltas]) => {
const doc = new Doc();
const text = doc.getText();
if (filePath in files) {
text.insert(0, files[filePath]);
if (filePath in data.files) {
text.insert(0, data.files[filePath]);
}
const contentAtStart = text.toString();
if (!selection.hasOwnProperty($session?.id)) {
selection[$session.id] = {};
}
if (!selection[$session.id].hasOwnProperty(filePath)) {
selection[$session?.id][filePath] = deltas.length - 1;
}
const operations = deltas
.filter((delta) => delta.timestampMs <= value)
.filter(
(_, index) => index <= selection[$session.id][filePath]
)
.flatMap((delta) => delta.operations);
operations.forEach((operation) => {
if (Operation.isInsert(operation)) {
text.insert(operation.insert[0], operation.insert[1]);
@ -37,36 +47,12 @@
text.delete(operation.delete[0], operation.delete[1]);
}
});
return [filePath, text.toString()];
const contentAfterDeltas = text.toString();
return [filePath, { a: contentAtStart, b: contentAfterDeltas }];
})
)
);
const contentWithDeltasApplied = (
contentAtSessionStart: string,
deltas: Delta[]
) => {
const doc = new Doc();
const text = doc.getText();
text.insert(0, contentAtSessionStart);
const operations = deltas.flatMap((delta) => delta.operations);
operations.forEach((operation) => {
if (Operation.isInsert(operation)) {
text.insert(operation.insert[0], operation.insert[1]);
} else if (Operation.isDelete(operation)) {
text.delete(operation.delete[0], operation.delete[1]);
}
});
return text.toString();
};
// const timestamps = Object.values(deltas).flatMap((deltas) =>
// Object.values(deltas).map((delta) => delta.timestampMs)
// );
// const min = Math.min(...timestamps);
// const max = Math.max(...timestamps);
// const showTimeline = isFinite(min) && isFinite(max);
</script>
<div class="flex flex-col w-full h-full overflow-hidden space-y-2">
@ -78,36 +64,30 @@
previousSesssion={$previousSesssion}
/>
</div>
<div class="overflow-auto h-2/3 mx-4">
{#each Object.entries(files) as [filepath, contentAtSessionStart]}
{#if $deltas[filepath]}
{#each Object.entries($docsNext) as [filepath, content]}
<details open>
<summary>
{filepath}
</summary>
<CodeViewer
value={contentAtSessionStart}
newValue={contentWithDeltasApplied(
contentAtSessionStart,
$deltas[filepath]
)}
/>
</details>
{/if}
{/each}
</div>
<div class="flex flex-col border-t border-zinc-700 mt-2">
{#each Object.entries($deltas) as [filepath, deltas]}
<div class="flex">
<div class="w-32">{filepath}</div>
<div class="flex space-x-2 items-center">
{#each deltas as delta}
<div class="cursor-pointer text-center items-center justify-center text-xs rounded-full h-4 w-4 bg-zinc-400 text-zinc-600 hover:bg-zinc-200" title="{toHumanReadableTime(delta.timestampMs)}">
<summary>{filepath}</summary>
<div class="flex flex-col">
<div class="flex space-x-1">
{#each $deltas[filepath] as delta, i}
<button
on:click={() => {
selection[$session.id][filepath] = i;
}}
class="{selection[$session.id][filepath] == i
? 'bg-orange-300'
: ''} text-center items-center justify-center text-xs rounded-full h-4 w-4 bg-zinc-400 text-zinc-600 hover:bg-zinc-200"
title={toHumanReadableTime(delta.timestampMs)}
>
<span>{delta.operations.length}</span>
</div>
</button>
{/each}
</div>
<CodeViewer value={content.a} newValue={content.b} />
</div>
</details>
{/each}
</div>
</div>

View File

@ -1,5 +1,5 @@
import type { PageLoad } from "./$types";
import { derived, readable } from "svelte/store";
import { derived, readable, writable } from "svelte/store";
import { building } from "$app/environment";
import type { Delta } from "$lib/deltas";
@ -19,8 +19,10 @@ export const load: PageLoad = async ({ parent, params }) => {
sessionId: params.sessionId,
});
return {
session: derived(sessions, (sessions) =>
sessions.find((session) => session.id === params.sessionId)
session: derived(sessions, (sessions) => {
const result = sessions.find((session) => session.id === params.sessionId)
return result ? result : sessions[0];
}
),
previousSesssion: derived(sessions, (sessions) => {
const currentSessionIndex = sessions.findIndex(