feat(settings): allow disabling update reminders
This commit is contained in:
parent
8c0fe3a6e7
commit
3eefe87380
|
|
@ -140,13 +140,18 @@ const activeConnection = computed(() => {
|
|||
});
|
||||
|
||||
function updateAgentDriverUpdateCount(count: number) {
|
||||
if (!settingsStore.editorSettings.updateNotificationsEnabled) {
|
||||
agentDriverUpdateCount.value = 0;
|
||||
return;
|
||||
}
|
||||
agentDriverUpdateCount.value = count;
|
||||
}
|
||||
|
||||
async function refreshAgentDriverUpdateCount() {
|
||||
if (!isDesktop) return;
|
||||
if (!isDesktop || !settingsStore.editorSettings.updateNotificationsEnabled) return;
|
||||
try {
|
||||
const drivers = await invoke<AgentDriverUpdateBadgeState[]>("list_installed_agents");
|
||||
if (!settingsStore.editorSettings.updateNotificationsEnabled) return;
|
||||
updateAgentDriverUpdateCount(countAvailableAgentDriverUpdates(drivers));
|
||||
} catch {
|
||||
// Driver update availability is only a badge hint; keep the existing count if the registry cannot be reached.
|
||||
|
|
@ -222,6 +227,11 @@ useVisibilityChange();
|
|||
|
||||
const appVersion = ref("");
|
||||
const isClassicLayout = computed(() => settingsStore.editorSettings.appLayout === "classic");
|
||||
const updateNotificationsEnabled = computed(() => settingsStore.editorSettings.updateNotificationsEnabled);
|
||||
const toolbarAgentDriverUpdateCount = computed(() =>
|
||||
updateNotificationsEnabled.value ? agentDriverUpdateCount.value : 0,
|
||||
);
|
||||
const toolbarHasUpdateAvailable = computed(() => updateNotificationsEnabled.value && hasUpdateAvailable.value);
|
||||
const hasSqlFileConnections = computed(() =>
|
||||
connectionStore.connections.some((c) => supportsSqlFileExecution(c.db_type)),
|
||||
);
|
||||
|
|
@ -878,6 +888,27 @@ function openDriverStoreFromEvent() {
|
|||
showDriverStore.value = true;
|
||||
}
|
||||
|
||||
function runUpdateNotificationChecks() {
|
||||
if (!updateNotificationsEnabled.value) return;
|
||||
checkUpdates({ silent: true });
|
||||
void refreshAgentDriverUpdateCount();
|
||||
}
|
||||
|
||||
watch(updateNotificationsEnabled, (enabled) => {
|
||||
if (!enabled) {
|
||||
agentDriverUpdateCount.value = 0;
|
||||
if (updateCheckTimer) {
|
||||
clearInterval(updateCheckTimer);
|
||||
updateCheckTimer = undefined;
|
||||
}
|
||||
return;
|
||||
}
|
||||
runUpdateNotificationChecks();
|
||||
if (!updateCheckTimer) {
|
||||
updateCheckTimer = setInterval(runUpdateNotificationChecks, UPDATE_CHECK_INTERVAL_MS);
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
console.log("[STARTUP] onMounted begin");
|
||||
const mountStart = performance.now();
|
||||
|
|
@ -915,14 +946,11 @@ onMounted(async () => {
|
|||
}
|
||||
initApp();
|
||||
setupFileDrop().catch(() => {});
|
||||
void refreshAgentDriverUpdateCount();
|
||||
setTimeout(() => {
|
||||
checkUpdates({ silent: true });
|
||||
void refreshAgentDriverUpdateCount();
|
||||
updateCheckTimer = setInterval(() => {
|
||||
checkUpdates({ silent: true });
|
||||
void refreshAgentDriverUpdateCount();
|
||||
}, UPDATE_CHECK_INTERVAL_MS);
|
||||
runUpdateNotificationChecks();
|
||||
if (updateNotificationsEnabled.value && !updateCheckTimer) {
|
||||
updateCheckTimer = setInterval(runUpdateNotificationChecks, UPDATE_CHECK_INTERVAL_MS);
|
||||
}
|
||||
}, 10_000);
|
||||
api
|
||||
.getAppVersion()
|
||||
|
|
@ -966,8 +994,8 @@ onUnmounted(() => {
|
|||
:show-history="showHistory"
|
||||
:show-driver-store="showDriverStore"
|
||||
:checking-updates="checkingUpdates"
|
||||
:has-update-available="hasUpdateAvailable"
|
||||
:agent-driver-update-count="agentDriverUpdateCount"
|
||||
:has-update-available="toolbarHasUpdateAvailable"
|
||||
:agent-driver-update-count="toolbarAgentDriverUpdateCount"
|
||||
:has-connections="connectionStore.connections.length > 0"
|
||||
:has-sql-file-connections="hasSqlFileConnections"
|
||||
@new-connection="showConnectionDialog = true"
|
||||
|
|
@ -1029,13 +1057,14 @@ onUnmounted(() => {
|
|||
<div class="h-full flex flex-col min-w-0">
|
||||
<AppTabBar
|
||||
:show-driver-store="showDriverStore"
|
||||
:agent-driver-update-count="agentDriverUpdateCount"
|
||||
:agent-driver-update-count="toolbarAgentDriverUpdateCount"
|
||||
@toggle-driver-store="showDriverStore = true"
|
||||
@close-driver-store="showDriverStore = false"
|
||||
/>
|
||||
<DriverStorePage
|
||||
v-if="showDriverStore"
|
||||
class="flex-1 min-h-0"
|
||||
:update-notifications-enabled="updateNotificationsEnabled"
|
||||
@update-count-change="updateAgentDriverUpdateCount"
|
||||
/>
|
||||
<div v-else-if="activeTab" class="flex flex-col flex-1 min-h-0">
|
||||
|
|
|
|||
|
|
@ -56,6 +56,15 @@ const { t } = useI18n();
|
|||
const { toast } = useToast();
|
||||
const isWeb = !isTauriRuntime();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
updateNotificationsEnabled?: boolean;
|
||||
}>(),
|
||||
{
|
||||
updateNotificationsEnabled: true,
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
"update-count-change": [count: number];
|
||||
}>();
|
||||
|
|
@ -117,7 +126,9 @@ const progressText = computed(() => {
|
|||
|
||||
const progressNumber = computed(() => driverInstallProgressPercent(progress.value));
|
||||
|
||||
const updatableCount = computed(() => drivers.value.filter((d) => d.update_available).length);
|
||||
const updatableCount = computed(() =>
|
||||
props.updateNotificationsEnabled ? drivers.value.filter((d) => d.update_available).length : 0,
|
||||
);
|
||||
const usageSummary = computed(() => {
|
||||
const usage = driverStoreUsage.value;
|
||||
if (!usage) return [];
|
||||
|
|
@ -142,10 +153,18 @@ function updateAgentDrivers(nextDrivers: AgentDriverInfo[]) {
|
|||
emitDriverUpdateCount();
|
||||
}
|
||||
|
||||
const agentTabUpdateCount = computed(() => drivers.value.filter((d) => d.update_available).length);
|
||||
const jdbcTabUpdateCount = computed(() => (jdbcPluginStatus.value?.update_available ? 1 : 0));
|
||||
const agentTabUpdateCount = computed(() =>
|
||||
props.updateNotificationsEnabled ? drivers.value.filter((d) => d.update_available).length : 0,
|
||||
);
|
||||
const jdbcTabUpdateCount = computed(() =>
|
||||
props.updateNotificationsEnabled && jdbcPluginStatus.value?.update_available ? 1 : 0,
|
||||
);
|
||||
|
||||
function emitDriverUpdateCount() {
|
||||
if (!props.updateNotificationsEnabled) {
|
||||
emit("update-count-change", 0);
|
||||
return;
|
||||
}
|
||||
emit("update-count-change", countAvailableDriverUpdates(drivers.value, jdbcPluginStatus.value));
|
||||
}
|
||||
|
||||
|
|
@ -722,9 +741,11 @@ onMounted(async () => {
|
|||
void loadJavaRuntimeConfig();
|
||||
void loadDriverStoreUsage();
|
||||
|
||||
api.listInstalledAgents().then((result) => {
|
||||
updateAgentDrivers(result);
|
||||
});
|
||||
if (props.updateNotificationsEnabled) {
|
||||
api.listInstalledAgents().then((result) => {
|
||||
updateAgentDrivers(result);
|
||||
});
|
||||
}
|
||||
|
||||
unlisten = await api.listenAgentInstallProgress((payload) => {
|
||||
if (payload.step === "done" || payload.step === "all-done") {
|
||||
|
|
@ -739,7 +760,7 @@ onMounted(async () => {
|
|||
}
|
||||
});
|
||||
void loadJdbcDrivers();
|
||||
void loadJdbcPluginStatus();
|
||||
if (props.updateNotificationsEnabled) void loadJdbcPluginStatus();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import type {
|
|||
TransportLayerConfig,
|
||||
} from "@/types/database";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { useSettingsStore } from "@/stores/settingsStore";
|
||||
import { useToast } from "@/composables/useToast";
|
||||
import DatabaseIcon from "@/components/icons/DatabaseIcon.vue";
|
||||
import * as api from "@/lib/api";
|
||||
|
|
@ -77,6 +78,7 @@ type ConnectionForm = Omit<ConnectionConfig, "id">;
|
|||
|
||||
const { t } = useI18n();
|
||||
const { toast } = useToast();
|
||||
const settingsStore = useSettingsStore();
|
||||
const open = defineModel<boolean>("open", { default: false });
|
||||
const isDesktop = isTauriRuntime();
|
||||
|
||||
|
|
@ -1688,6 +1690,7 @@ async function loadJdbcDrivers() {
|
|||
async function loadAgentDrivers() {
|
||||
try {
|
||||
agentDrivers.value = await api.listInstalledAgentsLocal();
|
||||
if (!settingsStore.editorSettings.updateNotificationsEnabled) return;
|
||||
api
|
||||
.listInstalledAgents()
|
||||
.then((drivers) => {
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ const editDisconnectTabHandlingMode = ref<DisconnectTabHandlingMode>(
|
|||
settingsStore.editorSettings.disconnectTabHandlingMode,
|
||||
);
|
||||
const editReuseDataTab = ref(settingsStore.editorSettings.reuseDataTab);
|
||||
const editUpdateNotificationsEnabled = ref(settingsStore.editorSettings.updateNotificationsEnabled);
|
||||
const editSidebarHiddenTablePrefixes = ref(settingsStore.editorSettings.sidebarHiddenTablePrefixes.join("\n"));
|
||||
const editSidebarHideTableComments = ref(settingsStore.editorSettings.sidebarHideTableComments);
|
||||
const editSidebarAllowHorizontalScroll = ref(settingsStore.editorSettings.sidebarAllowHorizontalScroll);
|
||||
|
|
@ -279,6 +280,7 @@ watch(
|
|||
editAutoSelectActiveSidebarNode.value = settingsStore.editorSettings.autoSelectActiveSidebarNode;
|
||||
editDisconnectTabHandlingMode.value = settingsStore.editorSettings.disconnectTabHandlingMode;
|
||||
editReuseDataTab.value = settingsStore.editorSettings.reuseDataTab;
|
||||
editUpdateNotificationsEnabled.value = settingsStore.editorSettings.updateNotificationsEnabled;
|
||||
editSidebarHiddenTablePrefixes.value = settingsStore.editorSettings.sidebarHiddenTablePrefixes.join("\n");
|
||||
editSidebarHideTableComments.value = settingsStore.editorSettings.sidebarHideTableComments;
|
||||
editSidebarAllowHorizontalScroll.value = settingsStore.editorSettings.sidebarAllowHorizontalScroll;
|
||||
|
|
@ -325,6 +327,7 @@ function hasChanges(): boolean {
|
|||
editAutoSelectActiveSidebarNode.value !== settingsStore.editorSettings.autoSelectActiveSidebarNode ||
|
||||
editDisconnectTabHandlingMode.value !== settingsStore.editorSettings.disconnectTabHandlingMode ||
|
||||
editReuseDataTab.value !== settingsStore.editorSettings.reuseDataTab ||
|
||||
editUpdateNotificationsEnabled.value !== settingsStore.editorSettings.updateNotificationsEnabled ||
|
||||
editSidebarHideTableComments.value !== settingsStore.editorSettings.sidebarHideTableComments ||
|
||||
editSidebarAllowHorizontalScroll.value !== settingsStore.editorSettings.sidebarAllowHorizontalScroll ||
|
||||
editExportBatchSize.value !== settingsStore.editorSettings.exportBatchSize ||
|
||||
|
|
@ -358,6 +361,7 @@ async function persistSettings() {
|
|||
autoSelectActiveSidebarNode: editAutoSelectActiveSidebarNode.value,
|
||||
disconnectTabHandlingMode: editDisconnectTabHandlingMode.value,
|
||||
reuseDataTab: editReuseDataTab.value,
|
||||
updateNotificationsEnabled: editUpdateNotificationsEnabled.value,
|
||||
sidebarHideTableComments: editSidebarHideTableComments.value,
|
||||
sidebarAllowHorizontalScroll: editSidebarAllowHorizontalScroll.value,
|
||||
sidebarHiddenTablePrefixes: normalizeSidebarHiddenTablePrefixes(editSidebarHiddenTablePrefixes.value),
|
||||
|
|
@ -404,6 +408,7 @@ function resetDefaults() {
|
|||
editAutoSelectActiveSidebarNode.value = DEFAULT_EDITOR_SETTINGS.autoSelectActiveSidebarNode;
|
||||
editDisconnectTabHandlingMode.value = DEFAULT_EDITOR_SETTINGS.disconnectTabHandlingMode;
|
||||
editReuseDataTab.value = DEFAULT_EDITOR_SETTINGS.reuseDataTab;
|
||||
editUpdateNotificationsEnabled.value = DEFAULT_EDITOR_SETTINGS.updateNotificationsEnabled;
|
||||
editSidebarHideTableComments.value = DEFAULT_EDITOR_SETTINGS.sidebarHideTableComments;
|
||||
editSidebarAllowHorizontalScroll.value = DEFAULT_EDITOR_SETTINGS.sidebarAllowHorizontalScroll;
|
||||
editSidebarHiddenTablePrefixes.value = DEFAULT_EDITOR_SETTINGS.sidebarHiddenTablePrefixes.join("\n");
|
||||
|
|
@ -1491,6 +1496,16 @@ watch(
|
|||
<Switch id="show-tray-icon" v-model="editShowTrayIcon" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-4 rounded-md border bg-muted/20 px-3 py-2">
|
||||
<div class="space-y-1">
|
||||
<Label for="update-notifications-enabled">{{ t("settings.updateNotificationsEnabled") }}</Label>
|
||||
<p class="text-xs text-muted-foreground">
|
||||
{{ t("settings.updateNotificationsEnabledDescription") }}
|
||||
</p>
|
||||
</div>
|
||||
<Switch id="update-notifications-enabled" v-model="editUpdateNotificationsEnabled" />
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div class="space-y-3">
|
||||
|
|
|
|||
|
|
@ -1629,6 +1629,9 @@ export default {
|
|||
showTrayIcon: "Show tray/menu bar icon",
|
||||
showTrayIconDescription:
|
||||
"When disabled, no icon is shown, but closing the window still hides DBX in the background as before.",
|
||||
updateNotificationsEnabled: "Enable update reminders",
|
||||
updateNotificationsEnabledDescription:
|
||||
"When disabled, DBX will not automatically check app or driver updates or show update badges. Manual checks are still available.",
|
||||
dataGridDisplay: "Data grid display",
|
||||
showColumnCommentsInHeader: "Show column comments under names",
|
||||
showColumnCommentsInHeaderDescription: "Display table column comments directly below grid column names.",
|
||||
|
|
|
|||
|
|
@ -1518,6 +1518,9 @@ export default {
|
|||
showTrayIcon: "Mostrar icono en bandeja/barra de menú",
|
||||
showTrayIconDescription:
|
||||
"Si está desactivado, no se muestra el icono, pero cerrar la ventana sigue ocultando DBX en segundo plano como antes.",
|
||||
updateNotificationsEnabled: "Activar recordatorios de actualización",
|
||||
updateNotificationsEnabledDescription:
|
||||
"Al desactivarlo, DBX no comprobará automáticamente actualizaciones de la app ni de los controladores, ni mostrará indicadores. Las comprobaciones manuales siguen disponibles.",
|
||||
dataGridDisplay: "Visualización de la tabla",
|
||||
showColumnCommentsInHeader: "Mostrar comentarios bajo los nombres",
|
||||
showColumnCommentsInHeaderDescription:
|
||||
|
|
|
|||
|
|
@ -1660,6 +1660,9 @@ export default {
|
|||
showTrayIcon: "Mostra icona nella barra delle applicazioni/menu",
|
||||
showTrayIconDescription:
|
||||
"Se disattivato, non viene mostrata alcuna icona, ma la chiusura della finestra nasconderà comunque DBX in background.",
|
||||
updateNotificationsEnabled: "Abilita promemoria aggiornamenti",
|
||||
updateNotificationsEnabledDescription:
|
||||
"Se disattivato, DBX non controllerà automaticamente gli aggiornamenti dell'app o dei driver e non mostrerà badge. I controlli manuali restano disponibili.",
|
||||
dataGridDisplay: "Visualizzazione griglia dati",
|
||||
showColumnCommentsInHeader: "Mostra i commenti delle colonne sotto i nomi",
|
||||
showColumnCommentsInHeaderDescription:
|
||||
|
|
|
|||
|
|
@ -1651,6 +1651,9 @@ export default {
|
|||
showTrayIcon: "Mostrar ícone na bandeja/barra de menus",
|
||||
showTrayIconDescription:
|
||||
"Quando desativado, nenhum ícone é exibido, mas fechar a janela ainda oculta o DBX em segundo plano como antes.",
|
||||
updateNotificationsEnabled: "Ativar lembretes de atualização",
|
||||
updateNotificationsEnabledDescription:
|
||||
"Quando desativado, o DBX não verificará automaticamente atualizações do app ou dos drivers nem mostrará indicadores. Verificações manuais continuam disponíveis.",
|
||||
dataGridDisplay: "Exibição da grade de dados",
|
||||
showColumnCommentsInHeader: "Mostrar comentários de coluna sob os nomes",
|
||||
showColumnCommentsInHeaderDescription:
|
||||
|
|
|
|||
|
|
@ -1599,6 +1599,9 @@ export default {
|
|||
iconThemeBlackDescription: "窗口、托盘和 Logo 都使用黑色 DBX 标识。",
|
||||
showTrayIcon: "显示系统托盘/菜单栏图标",
|
||||
showTrayIconDescription: "关闭后不显示图标,但关闭窗口仍会像之前一样隐藏到后台。",
|
||||
updateNotificationsEnabled: "启用更新提醒",
|
||||
updateNotificationsEnabledDescription:
|
||||
"关闭后,DBX 不会自动检查应用和驱动更新,也不会显示更新红点;仍可手动检查更新。",
|
||||
dataGridDisplay: "数据表格显示",
|
||||
showColumnCommentsInHeader: "在字段名下方显示注释",
|
||||
showColumnCommentsInHeaderDescription: "把表字段注释直接显示在结果表头字段名下方。",
|
||||
|
|
|
|||
|
|
@ -1575,6 +1575,9 @@ export default {
|
|||
iconThemeBlackDescription: "視窗、系統匣和 Logo 都使用黑色 DBX 標誌。",
|
||||
showTrayIcon: "顯示系統匣/選單欄圖示",
|
||||
showTrayIconDescription: "關閉後不顯示圖示,但關閉視窗仍會像之前一樣隱藏到後台。",
|
||||
updateNotificationsEnabled: "啟用更新提醒",
|
||||
updateNotificationsEnabledDescription:
|
||||
"關閉後,DBX 不會自動檢查應用程式和驅動程式更新,也不會顯示更新紅點;仍可手動檢查更新。",
|
||||
dataGridDisplay: "資料表格顯示",
|
||||
showColumnCommentsInHeader: "在欄位名稱下方顯示註解",
|
||||
showColumnCommentsInHeaderDescription: "直接在資料表格欄位名稱下方顯示資料表欄位註解。",
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ export interface EditorSettings {
|
|||
autoSelectActiveSidebarNode: boolean;
|
||||
disconnectTabHandlingMode: DisconnectTabHandlingMode;
|
||||
reuseDataTab: boolean;
|
||||
updateNotificationsEnabled: boolean;
|
||||
sidebarHiddenTablePrefixes: string[];
|
||||
sidebarHideTableComments: boolean;
|
||||
sidebarAllowHorizontalScroll: boolean;
|
||||
|
|
@ -322,6 +323,7 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
|
|||
autoSelectActiveSidebarNode: false,
|
||||
disconnectTabHandlingMode: "close-tabs",
|
||||
reuseDataTab: false,
|
||||
updateNotificationsEnabled: true,
|
||||
sidebarHiddenTablePrefixes: [],
|
||||
sidebarHideTableComments: false,
|
||||
sidebarAllowHorizontalScroll: false,
|
||||
|
|
@ -495,6 +497,8 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
|||
(settings as Partial<EditorSettings> & { closeQueryTabsOnDisconnect?: boolean }).closeQueryTabsOnDisconnect,
|
||||
),
|
||||
reuseDataTab: settings.reuseDataTab ?? DEFAULT_EDITOR_SETTINGS.reuseDataTab,
|
||||
updateNotificationsEnabled:
|
||||
settings.updateNotificationsEnabled ?? DEFAULT_EDITOR_SETTINGS.updateNotificationsEnabled,
|
||||
sidebarHiddenTablePrefixes: normalizeSidebarHiddenTablePrefixes(settings.sidebarHiddenTablePrefixes),
|
||||
sidebarHideTableComments: settings.sidebarHideTableComments ?? DEFAULT_EDITOR_SETTINGS.sidebarHideTableComments,
|
||||
sidebarAllowHorizontalScroll:
|
||||
|
|
@ -667,6 +671,8 @@ export const useSettingsStore = defineStore("settings", () => {
|
|||
partial.disconnectTabHandlingMode,
|
||||
);
|
||||
if (partial.reuseDataTab !== undefined) editorSettings.value.reuseDataTab = partial.reuseDataTab;
|
||||
if (partial.updateNotificationsEnabled !== undefined)
|
||||
editorSettings.value.updateNotificationsEnabled = partial.updateNotificationsEnabled;
|
||||
if (partial.sidebarHiddenTablePrefixes !== undefined)
|
||||
editorSettings.value.sidebarHiddenTablePrefixes = normalizeSidebarHiddenTablePrefixes(
|
||||
partial.sidebarHiddenTablePrefixes,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ test("defaults dangerous SQL confirmation to enabled", () => {
|
|||
assert.equal(normalizeEditorSettings({ confirmDangerousSqlExecution: false }).confirmDangerousSqlExecution, false);
|
||||
});
|
||||
|
||||
test("defaults update notifications to enabled", () => {
|
||||
assert.equal(DEFAULT_EDITOR_SETTINGS.updateNotificationsEnabled, true);
|
||||
assert.equal(normalizeEditorSettings({}).updateNotificationsEnabled, true);
|
||||
assert.equal(normalizeEditorSettings({ updateNotificationsEnabled: false } as any).updateNotificationsEnabled, false);
|
||||
});
|
||||
|
||||
test("defaults shortcut settings", () => {
|
||||
const settings = normalizeEditorSettings({});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue