Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions client/dive-common/components/TrackSettingsPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default defineComponent({
filterTracksByFrame: 'Filter the track list by those with detections in the current frame',
autoZoom: 'Automatically zoom to the track when selected',
showMultiCamToolbar: 'Show multi-camera tools in the top toolbar when a track is selected',
autoSave: 'Automatically save annotation changes after a short delay. Changes are batched to reduce server requests.',
});
const modes = ref(['Track', 'Detection']);
// Add unknown as the default type to the typeList
Expand Down Expand Up @@ -362,6 +363,45 @@ export default defineComponent({
</v-tooltip>
</v-col>
</v-row>
<v-divider class="my-2" />
<div class="subheading">
Auto-Save Settings
</div>
<v-row
align="end"
dense
>
<v-col class="py-1">
<v-switch
v-model="clientSettings.autoSaveSettings.enabled"
class="my-0 ml-1 pt-0"
dense
label="Auto-Save"
hide-details
/>
</v-col>
<v-col
cols="2"
class="py-1"
align="right"
>
<v-tooltip
open-delay="200"
max-width="200"
bottom
>
<template #activator="{ on }">
<v-icon
small
v-on="on"
>
mdi-help
</v-icon>
</template>
<span>{{ help.autoSave }}</span>
</v-tooltip>
</v-col>
</v-row>
</v-card>
</div>
</template>
36 changes: 32 additions & 4 deletions client/dive-common/components/Viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,11 @@ export default defineComponent({
handler.stopLinking();
}
});
async function save(setVal?: string) {
// If editing the track, disable editing mode before save
async function save(setVal?: string, exitEditingMode = false) {
// Only exit editing mode if explicitly requested (e.g., manual save)
// Auto-save should NOT disrupt the user's editing session
saveInProgress.value = true;
if (editingTrack.value) {
if (exitEditingMode && editingTrack.value) {
handler.trackSelect(selectedTrackId.value, false);
}
const saveSet = setVal === 'default' ? undefined : setVal;
Expand Down Expand Up @@ -467,6 +468,32 @@ export default defineComponent({

watch(imageEnhancements, debouncedSaveImageEnhancements, { deep: true });

// Auto-save annotations when enabled
const debouncedAutoSave = debounce(
async () => {
if (readonlyState.value) return;
if (pendingSaveCount.value === 0) return;
if (saveInProgress.value) return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if a user makes a change while a save is happening? I assume that this debounced function will be scheduled, but may end up returning early if a previous save is still in progress.

Should we also be watching saveInProgress, and check to see if we need to retry the save after the value changes from true to false?

await save(props.currentSet);
},
2000,
{ trailing: true, leading: false },
);

watch(
pendingSaveCount,
(newCount, oldCount) => {
if (
clientSettings.autoSaveSettings.enabled
&& newCount > oldCount
&& newCount > 0
&& !readonlyState.value
) {
debouncedAutoSave();
}
},
);

// Navigation Guards used by parent component
async function warnBrowserExit(event: BeforeUnloadEvent) {
if (pendingSaveCount.value === 0) return;
Expand Down Expand Up @@ -766,6 +793,7 @@ export default defineComponent({
handleResize();
});
onBeforeUnmount(() => {
debouncedAutoSave.cancel();
if (controlsRef.value) observer.unobserve(controlsRef.value.$el);
});

Expand Down Expand Up @@ -1081,7 +1109,7 @@ export default defineComponent({
@click="save(currentSet)"
>
<v-icon>
mdi-content-save
{{ clientSettings.autoSaveSettings.enabled ? 'mdi-content-save-cog' : 'mdi-content-save' }}
</v-icon>
</v-btn>
</div>
Expand Down
6 changes: 6 additions & 0 deletions client/dive-common/store/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ interface AnnotationSettings {
multiCamSettings: {
showToolbar: boolean;
};
autoSaveSettings: {
enabled: boolean;
};
}

const defaultSettings: AnnotationSettings = {
Expand Down Expand Up @@ -105,6 +108,9 @@ const defaultSettings: AnnotationSettings = {
multiCamSettings: {
showToolbar: true,
},
autoSaveSettings: {
enabled: false, // Disabled by default for backward compatibility
},
};

// Utility to safely load from localStorage
Expand Down
12 changes: 12 additions & 0 deletions client/platform/desktop/frontend/components/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,18 @@ export default defineComponent({
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-switch
v-model="clientSettings.autoSaveSettings.enabled"
color="primary"
label="Auto-save annotations"
hint="Automatically save annotation changes after a short delay. Changes are batched to reduce server requests."
persistent-hint
class="my-0"
/>
</v-col>
</v-row>
</v-card-text>

<v-card-title>Platform support</v-card-title>
Expand Down
38 changes: 35 additions & 3 deletions client/platform/web-girder/views/Settings.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
<script lang="ts">
import Vue from 'vue';
import { defineComponent } from 'vue';
import { clientSettings } from 'dive-common/store/settings';

export default Vue.extend({
export default defineComponent({
name: 'Settings',
setup() {
return {
clientSettings,
};
},
});
</script>

<template>
<v-container>
<v-card>
<v-card-title>
<!-- NEW GLOBAL SETTINGS ADDED HERE -->
Annotation Settings
</v-card-title>
<v-card-text>
<v-row>
<v-col>
<v-switch
v-model="clientSettings.multiCamSettings.showToolbar"
color="primary"
label="Show multi-camera toolbar"
hint="Show multi-camera editing tools in the top toolbar when a track is selected"
persistent-hint
class="my-0"
/>
</v-col>
</v-row>
Comment on lines +22 to +33
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this isn't related to auto-save, and we don't yet support stereo/multi camera in web, should we remove this for now?

<v-row>
<v-col>
<v-switch
v-model="clientSettings.autoSaveSettings.enabled"
color="primary"
label="Auto-save annotations"
hint="Automatically save annotation changes after a short delay. Changes are batched to reduce server requests."
persistent-hint
class="my-0"
/>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-container>
</template>
Loading