Merge branch 'master' into btn-grp

This commit is contained in:
Ian Donahue 2023-03-28 17:04:50 +02:00
commit e8468fa137
8 changed files with 122 additions and 129 deletions

8
src-tauri/Cargo.lock generated
View File

@ -2432,9 +2432,9 @@ dependencies = [
[[package]]
name = "openssl"
version = "0.10.45"
version = "0.10.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2"
dependencies = [
"bitflags",
"cfg-if",
@ -2473,9 +2473,9 @@ dependencies = [
[[package]]
name = "openssl-sys"
version = "0.9.80"
version = "0.9.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b"
dependencies = [
"autocfg",
"cc",

View File

@ -3,12 +3,6 @@
@tailwind components;
@tailwind utilities;
/* this is trick to make webkit use hardware acceleration */
*:not(html) {
-webkit-transform: translate3d(0, 0, 0);
-webkit-perspective: 1000;
}
/* SCROLL BAR STYLING */
/* width */

View File

@ -23,32 +23,8 @@ export type DeltasEvent = {
filePath: string;
};
const cache: Record<string, Record<string, Promise<Record<string, Delta[]>>>> = {};
export const list = async (params: { projectId: string; sessionId: string; paths?: string[] }) => {
const sessionCache = cache[params.projectId] || {};
if (params.sessionId in sessionCache) {
return sessionCache[params.sessionId].then((deltas) =>
Object.fromEntries(
Object.entries(deltas).filter(([path]) =>
params.paths ? params.paths.includes(path) : true
)
)
);
}
const promise = invoke<Record<string, Delta[]>>('list_deltas', {
projectId: params.projectId,
sessionId: params.sessionId
});
sessionCache[params.sessionId] = promise;
cache[params.projectId] = sessionCache;
return promise.then((deltas) =>
Object.fromEntries(
Object.entries(deltas).filter(([path]) => (params.paths ? params.paths.includes(path) : true))
)
);
};
export const list = async (params: { projectId: string; sessionId: string; paths?: string[] }) =>
invoke<Record<string, Delta[]>>('list_deltas', params);
export const subscribe = (
params: { projectId: string; sessionId: string },

View File

@ -62,7 +62,7 @@ export const listFiles = async (params: {
const sessionsCache: Record<string, Promise<Session[]>> = {};
const list = async (params: { projectId: string; earliestTimestampMs?: number }) => {
export const list = async (params: { projectId: string; earliestTimestampMs?: number }) => {
if (params.projectId in sessionsCache) {
return sessionsCache[params.projectId].then((sessions) =>
sessions.filter((s) =>

View File

@ -4,10 +4,11 @@
import { Toaster } from 'svelte-french-toast';
import type { LayoutData } from './$types';
import { BackForwardButtons } from '$lib/components';
import { setContext } from 'svelte';
import { onMount, setContext } from 'svelte';
import { writable } from 'svelte/store';
import Breadcrumbs from '$lib/components/Breadcrumbs.svelte';
import CommandPalette from '$lib/components/CommandPalette';
import { list as listSessions, listFiles } from '$lib/sessions';
export let data: LayoutData;
const { user, posthog, projects } = data;
@ -16,6 +17,16 @@
setContext('session', writable(null));
setContext('projects', projects);
onMount(() =>
// warm up the cache
$projects.forEach(async (project) => {
const sessions = await listSessions({ projectId: project.id });
sessions.forEach(async (session) => {
listFiles({ projectId: project.id, sessionId: session.id });
});
})
);
user.subscribe(posthog.identify);
</script>

View File

@ -1,5 +1,7 @@
<script lang="ts">
import { page } from '$app/stores';
import { list as listDeltas } from '$lib/deltas';
import { asyncDerived } from '@square/svelte-store';
import { format } from 'date-fns';
import { derived } from 'svelte/store';
import type { LayoutData } from './$types';
@ -7,63 +9,76 @@
export let data: LayoutData;
const { sessions, projectId } = data;
const dates = derived(sessions, (sessions) =>
sessions
const fileFilter = derived(page, (page) => page.url.searchParams.get('file'));
const dates = asyncDerived([sessions, fileFilter], async ([sessions, fileFilter]) => {
const sessionFiles = await Promise.all(
sessions.map((session) =>
listDeltas({
projectId,
sessionId: session.id,
paths: fileFilter ? [fileFilter] : undefined
})
)
);
return sessions
.filter((_, index) => Object.keys(sessionFiles[index]).length > 0)
.map((session) => session.meta.startTimestampMs)
.sort((a, b) => b - a)
.map((ts) => format(new Date(ts), 'yyyy-MM-dd'))
.filter((date, index, self) => self.indexOf(date) === index)
);
.filter((date, index, self) => self.indexOf(date) === index);
});
const currentDate = derived(page, (page) => page.params.date);
const today = format(new Date(), 'yyyy-MM-dd');
const fileFilter = derived(page, (page) => page.url.searchParams.get('file'));
</script>
{#if $sessions.length === 0}
<div class="text-center">
<h2 class="text-xl">I haven't seen any changes yet</h2>
<p class="text-gray-500">Go code something!</p>
</div>
{:else}
{#if $fileFilter}
<a
href="/projects/{$page.params.projectId}/player/{$page.params.date}/{$page.params.sessionId}"
class="w-full p-2 text-left font-mono text-lg"
>
{$fileFilter}
</a>
{#await dates.load() then}
{#if $sessions.length === 0}
<div class="text-center">
<h2 class="text-xl">I haven't seen any changes yet</h2>
<p class="text-gray-500">Go code something!</p>
</div>
{:else}
{#if $fileFilter}
<a
href="/projects/{$page.params.projectId}/player/{$page.params.date}/{$page.params
.sessionId}"
class="w-full p-2 text-left font-mono text-lg"
>
{$fileFilter}
</a>
{/if}
<div class="flex h-full w-full flex-row gap-2 px-2">
<ul
id="days"
class="scrollbar-hidden grid h-full flex-shrink-0 auto-rows-min gap-2 overflow-y-scroll py-2"
>
{#each $dates as date}
{@const isToday = format(new Date(date), 'yyyy-MM-dd') === today}
<li>
<a
href="/projects/{projectId}/player/{date}{$page.url.search}"
class:bg-gb-800={date === $currentDate}
class:text-white={date === $currentDate}
class:border-gb-700={date !== $currentDate}
class:bg-gb-900={date !== $currentDate}
class="max-h-content flex w-full flex-col items-center justify-around rounded border border-[0.5px] p-2 text-zinc-300 shadow transition duration-150 ease-out hover:bg-gb-800 hover:ease-in"
>
{#if isToday}
<div class="py-2 text-lg leading-5">Today</div>
{:else}
<div class="text-xl leading-5">{new Date(date).getDate()}</div>
<div class="leading-4">{format(new Date(date), 'MMM')}</div>
{/if}
</a>
</li>
{/each}
</ul>
<slot />
</div>
{/if}
<div class="flex h-full w-full flex-row gap-2 px-2">
<ul
id="days"
class="scrollbar-hidden grid h-full flex-shrink-0 auto-rows-min gap-2 overflow-y-scroll py-2"
>
{#each $dates as date}
{@const isToday = format(new Date(date), 'yyyy-MM-dd') === today}
<li>
<a
href="/projects/{projectId}/player/{date}{$page.url.search}"
class:bg-gb-800={date === $currentDate}
class:text-white={date === $currentDate}
class:border-gb-700={date !== $currentDate}
class:bg-gb-900={date !== $currentDate}
class="max-h-content flex w-full flex-col items-center justify-around rounded border border-[0.5px] p-2 text-zinc-300 shadow transition duration-150 ease-out hover:bg-gb-800 hover:ease-in"
>
{#if isToday}
<div class="py-2 text-lg leading-5">Today</div>
{:else}
<div class="text-xl leading-5">{new Date(date).getDate()}</div>
<div class="leading-4">{format(new Date(date), 'MMM')}</div>
{/if}
</a>
</li>
{/each}
</ul>
<slot />
</div>
{/if}
{/await}

View File

@ -271,7 +271,7 @@
<div
id="player"
class="relative my-2 flex flex-auto overflow-auto rounded border border-zinc-700 bg-gb-900"
class="relative my-2 flex flex-auto flex-col overflow-auto rounded border border-zinc-700 bg-gb-900"
>
{#if $frame}
<div id="code" class="h-full w-full flex-auto overflow-auto px-2 pb-[120px]">
@ -298,14 +298,7 @@
<div
id="controls"
class="absolute bottom-0 flex w-full flex-col border-t border-zinc-700 bg-[#2E2E32]/75 p-2 pt-4"
style="
border-width: 0.5px;
-webkit-backdrop-filter: blur(5px) saturate(190%) contrast(70%) brightness(80%);
backdrop-filter: blur(5px) saturate(190%) contrast(70%) brightness(80%);
background-color: rgba(24, 24, 27, 0.60);
border: 0.5px solid rgba(63, 63, 70, 0.50);
"
class="flex w-full flex-col border-t border-zinc-700 bg-[#2E2E32]/75 p-2 pt-4"
>
<div class="flex h-0 w-full justify-between">
{#each $richSessions as session}

View File

@ -11,6 +11,7 @@ const meta: Meta<Button> = {
primary: { control: 'boolean' },
outlined: { control: 'boolean' },
small: { control: 'boolean' },
wide: { control: 'boolean' },
label: { control: 'text' }
}
};
@ -19,6 +20,41 @@ export default meta;
type Story = StoryObj<Button>;
// More on writing stories with args: https://storybook.js.org/docs/7.0/svelte/writing-stories/args
export const Basic: Story = {
args: {
primary: false,
outlined: false,
label: 'Label'
}
};
export const BasicOutlined: Story = {
args: {
primary: false,
outlined: true,
label: 'Button'
}
};
export const BasicSmall: Story = {
args: {
primary: false,
outlined: false,
small: true,
label: 'Button'
}
};
export const BasicOutlinedSmall: Story = {
args: {
primary: false,
outlined: true,
small: true,
label: 'Button'
}
};
export const Primary: Story = {
args: {
primary: true,
@ -70,36 +106,4 @@ export const PrimaryOutlinedSmall: Story = {
}
};
export const Default: Story = {
args: {
primary: false,
outlined: false,
label: 'Label'
}
};
export const DefaultOutlined: Story = {
args: {
primary: false,
outlined: true,
label: 'Button'
}
};
export const DefaultSmall: Story = {
args: {
primary: false,
outlined: false,
small: true,
label: 'Button'
}
};
export const DefaultOutlinedSmall: Story = {
args: {
primary: false,
outlined: true,
small: true,
label: 'Button'
}
};