Skip to content

Commit c030856

Browse files
committed
#6: Guarding against multiple any kind of save with duplicate file contents
Also fixing toast behavior. It wasn't stacking properly if there was a permanent toast because it threw off the calculation of toasts to render next.
1 parent 5465afd commit c030856

File tree

7 files changed

+31
-19
lines changed

7 files changed

+31
-19
lines changed

src/components/YvRepl.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useIntervalFn } from '@vueuse/core';
77
import { useFileManagerStore } from '@/composables/useFileManagerStore';
88
import { useSettingsStore } from '@/composables/useSettingsStore';
99
10-
const AUTO_SAVE_INTERVAL_MINUTES = 3 * 60 * 1000;
10+
const AUTO_SAVE_INTERVAL_MINUTES = 10 * 60 * 1000;
1111
1212
const { settings } = useSettingsStore();
1313
const fm = useFileManagerStore();

src/components/YvSidebar/YvSidebar.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ function handleScroll() {
7171
<div
7272
v-else
7373
v-bind="containerProps"
74-
class="p-2 overflow-auto" flex="~ grow-1"
75-
h-full
74+
flex="~ grow-1"
75+
overflow-auto
76+
h-full pt-4
7677
@scroll="handleScroll"
7778
>
7879
<ul v-bind="wrapperProps" mb-8>

src/components/YvVersioningDrawer/YvSnapshot.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const didFilesChange = computed(() => {
6868
:exit="{ opacity: 0, scale: 0 }"
6969
:transition="props.disableAnimation ? { duration: 0 } : { duration: 0.25, ease: 'easeOut' }"
7070
px-4 layout h-28
71-
class="group/snapshot hover-bg-accent/60 dark:hover-bg-accent/10"
71+
class="group/snapshot hover-bg-accent/60 dark:hover-bg-accent/20"
7272
>
7373
<div flex="~ items-center justify-between" mb-1>
7474
<div flex gap-0 items-center>

src/components/toasts/YvToasts.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,18 +135,19 @@ watchEffect(() => {
135135
});
136136
137137
// --- STACKING LOGIC ---
138-
const stackLimit = props.stackLimit || 4; // Number of toasts visible by default
138+
const stackLimit = computed(() => props.stackLimit ?? 4);
139139
const isStackHovered = ref(false);
140140
141141
const visibleToasts = computed(() => {
142142
if (isStackHovered.value)
143143
return activeToasts;
144-
return activeToasts.slice(0, stackLimit);
144+
145+
// Always show the newest ones
146+
return activeToasts.slice(-stackLimit.value);
145147
});
146148
147149
const hiddenCount = computed(() => {
148-
const count = activeToasts.length - stackLimit;
149-
return count > 0 ? count : 0;
150+
return Math.max(0, activeToasts.length - visibleToasts.value.length);
150151
});
151152
</script>
152153

src/components/toasts/useToastsStore.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,28 @@ type Toast = {
99
title: string;
1010
description: string;
1111
duration?: number;
12+
createdTimestamp: number;
1213
};
1314

1415
const defaultToast: Omit<Toast, 'id'> = {
1516
type: 'info',
1617
title: '',
1718
description: '',
1819
duration: 4000,
20+
createdTimestamp: 0,
1921
};
2022

2123
export const useToastsStore = defineStore('toastStore', () => {
2224
const activeToasts = reactive<Toast[]>([]);
2325

2426
function addToast(toast: Omit<Partial<Toast>, 'id'>): string {
2527
const id = crypto.randomUUID().slice(0, 8);
26-
activeToasts.push({ id, ...defaultToast, ...toast });
28+
activeToasts.push({
29+
id,
30+
...defaultToast,
31+
...toast,
32+
createdTimestamp: Date.now(),
33+
});
2734
return id;
2835
};
2936

src/composables/useFileManagerStore.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ export const useFileManagerStore = defineStore('file-manager', () => {
8989
return;
9090
}
9191

92-
const latestManualSnapshot = await snapshots.getLatestManualSnapshot();
92+
const latestSnapshotByType = await snapshots.getLatestByType(snapshot.type);
9393

94-
if (snapshot.type !== 'manual' || !latestManualSnapshot) {
94+
if (!latestSnapshotByType) {
9595
snapshots.create({
9696
sessionId: currentSession.value.id,
9797
files: replStore.getFiles(),
@@ -102,7 +102,7 @@ export const useFileManagerStore = defineStore('file-manager', () => {
102102
sessions.changeUpdatedAt(currentSession.value.id, new Date());
103103
}
104104
else {
105-
const didFilesChange = replStore.getFiles()['App.vue'] !== latestManualSnapshot.files['App.vue'];
105+
const didFilesChange = replStore.getFiles()['App.vue'] !== latestSnapshotByType.files['App.vue'];
106106

107107
if (didFilesChange) {
108108
snapshots.create({
@@ -113,11 +113,14 @@ export const useFileManagerStore = defineStore('file-manager', () => {
113113
});
114114

115115
sessions.changeUpdatedAt(currentSession.value.id, new Date());
116-
toast.success('Snapshot saved');
116+
if (snapshot.type === 'manual') {
117+
toast.success('Snapshot saved');
118+
}
117119
}
118120
else {
119-
// toast.info('Nothing new to save', { duration: Infinity });
120-
toast.info('Nothing new to save');
121+
if (snapshot.type === 'manual') {
122+
toast.info('Nothing new to save');
123+
}
121124
}
122125
}
123126
}

src/db/snapshots.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import type { Observable } from 'dexie';
22

3-
import type { Snapshot } from '@/db';
3+
import type { Snapshot, SnapshotType } from '@/db';
44
import { liveQuery } from 'dexie';
55

66
import { db } from '@/db';
77

88
export const snapshots = {
99
create,
1010
liveQuerySnapshots,
11-
getLatestManualSnapshot,
11+
getLatestByType,
1212
deleteSnapshot,
1313
};
1414

@@ -31,8 +31,8 @@ function liveQuerySnapshots(sessionId: number): Observable<Snapshot[]> {
3131
return liveQuery(async () => await db.snapshots.where({ sessionId }).reverse().sortBy('createdAt'));
3232
}
3333

34-
async function getLatestManualSnapshot(): Promise<Snapshot | undefined> {
35-
return (await db.snapshots.where({ type: 'manual' }).sortBy('createdAt')).pop();
34+
async function getLatestByType(type: SnapshotType): Promise<Snapshot | undefined> {
35+
return (await db.snapshots.where({ type }).sortBy('createdAt')).pop();
3636
}
3737

3838
function deleteSnapshot(snapshotId: number): Promise<void> {

0 commit comments

Comments
 (0)