{{ toastMessage }}
@@ -2857,7 +2935,7 @@ onUnmounted(() => {
-
+
@@ -2895,6 +2973,26 @@ onUnmounted(() => {
diff --git a/apps/desktop/src/components/layout/AppToolbar.vue b/apps/desktop/src/components/layout/AppToolbar.vue
index 2601cbe4f0..8e155b67e3 100644
--- a/apps/desktop/src/components/layout/AppToolbar.vue
+++ b/apps/desktop/src/components/layout/AppToolbar.vue
@@ -29,6 +29,7 @@ const props = defineProps<{
showAiPanel: boolean;
showHistory: boolean;
showSqlLibrary: boolean;
+ sqlLibrarySaveFeedbackId: number;
showSqlFilePanel: boolean;
showDriverStore: boolean;
showSettingsPage: boolean;
@@ -64,6 +65,41 @@ const settingsStore = useSettingsStore();
const toolbarItems = computed(() => settingsStore.editorSettings.toolbarItems);
const { isMac, isDesktop, showControls, isMaximized, isFullscreen, minimize, toggleMaximize, close } = useWindowControls();
const checkingUpdates = computed(() => props.checkingUpdates);
+const sqlLibrarySaveFeedbackActive = ref(false);
+const SQL_LIBRARY_BOOKMARK_PATH = "M10 2 L10 10 L13 7 L16 10 L16 2";
+const SQL_LIBRARY_CHECK_PATH = "M9 9.5 L9 9.5 L11 11.5 L15 7.5 L15 7.5";
+type SvgAnimateElement = SVGElement & { beginElement?: () => void };
+const sqlLibraryIconPathRef = ref
(null);
+const sqlLibraryMorphToCheckRef = ref(null);
+const sqlLibraryMorphToBookmarkRef = ref(null);
+let sqlLibrarySaveFeedbackTimer = 0;
+
+watch(
+ () => props.sqlLibrarySaveFeedbackId,
+ async (id, previousId) => {
+ if (id <= 0 || id === previousId) return;
+ sqlLibrarySaveFeedbackActive.value = false;
+ await nextTick();
+ sqlLibrarySaveFeedbackActive.value = true;
+ window.clearTimeout(sqlLibrarySaveFeedbackTimer);
+ sqlLibrarySaveFeedbackTimer = window.setTimeout(() => {
+ sqlLibrarySaveFeedbackActive.value = false;
+ }, 850);
+ },
+);
+
+watch(sqlLibrarySaveFeedbackActive, async (active) => {
+ await nextTick();
+ const path = sqlLibraryIconPathRef.value;
+ const animation = active ? sqlLibraryMorphToCheckRef.value : sqlLibraryMorphToBookmarkRef.value;
+ const destination = active ? SQL_LIBRARY_CHECK_PATH : SQL_LIBRARY_BOOKMARK_PATH;
+ if (!path) return;
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches || !animation?.beginElement) {
+ path.setAttribute("d", destination);
+ return;
+ }
+ animation.beginElement();
+});
const themeTriggerIcon = computed(() => {
if (isSystemAppThemeMode(props.themeMode)) return SunMoon;
@@ -351,6 +387,7 @@ onMounted(() => {
onBeforeUnmount(() => {
if (toolbarLayoutRaf) cancelAnimationFrame(toolbarLayoutRaf);
if (trafficLightSyncRaf) cancelAnimationFrame(trafficLightSyncRaf);
+ window.clearTimeout(sqlLibrarySaveFeedbackTimer);
resizeObserver?.disconnect();
window.removeEventListener("resize", handleWindowResize);
});
@@ -559,8 +596,27 @@ const toolbarStyle = computed(() => {
-
{{ t("sqlLibrary.title") }}
@@ -630,3 +686,58 @@ const toolbarStyle = computed(() => {
+
+