Add server config modified message to prompt restart (#1668)

* Server config changed message

* Write to settings on unmount

* nit

* Highlight modified config

* Move modified logic to store

* Add jest test

* nit
This commit is contained in:
Chenlei Hu
2024-11-24 13:13:37 -08:00
committed by GitHub
parent 4a4d6d070a
commit c61ed4da37
9 changed files with 138 additions and 24 deletions

View File

@@ -1,7 +1,7 @@
<!-- A generalized form item for rendering in a form. -->
<template>
<div class="form-label flex flex-grow items-center">
<span class="text-[var(--p-text-muted-color)]">
<span class="text-muted" :class="props.labelClass">
<slot name="name-prefix"></slot>
{{ props.item.name }}
<i
@@ -33,15 +33,11 @@ import CustomFormValue from '@/components/common/CustomFormValue.vue'
import InputSlider from '@/components/common/InputSlider.vue'
const formValue = defineModel<any>('formValue')
const props = withDefaults(
defineProps<{
item: FormItem
id: string | undefined
}>(),
{
id: undefined
}
)
const props = defineProps<{
item: FormItem
id?: string
labelClass?: string | Record<string, boolean>
}>()
function getFormAttrs(item: FormItem) {
const attrs = { ...(item.attrs || {}) }

View File

@@ -1,4 +1,27 @@
<template>
<Message v-if="modifiedConfigs.length > 0" severity="info" pt:text="w-full">
<p>
{{ $t('serverConfig.modifiedConfigs') }}
</p>
<ul>
<li v-for="config in modifiedConfigs" :key="config.id">
{{ config.name }}: {{ config.initialValue }} {{ config.value }}
</li>
</ul>
<div class="flex justify-end gap-2">
<Button
:label="$t('serverConfig.revertChanges')"
@click="revertChanges"
outlined
/>
<Button
:label="$t('serverConfig.restart')"
@click="restartApp"
outlined
severity="danger"
/>
</div>
</Message>
<div
v-for="([label, items], i) in Object.entries(serverConfigsByCategory)"
:key="label"
@@ -6,32 +29,48 @@
<Divider v-if="i > 0" />
<h3>{{ formatCamelCase(label) }}</h3>
<div v-for="item in items" :key="item.name" class="flex items-center mb-4">
<FormItem :item="item" v-model:formValue="item.value" />
<FormItem
:item="item"
v-model:formValue="item.value"
:id="item.id"
:labelClass="{
'text-highlight': item.initialValue !== item.value
}"
/>
</div>
</div>
</template>
<script setup lang="ts">
import Button from 'primevue/button'
import Message from 'primevue/message'
import Divider from 'primevue/divider'
import FormItem from '@/components/common/FormItem.vue'
import { formatCamelCase } from '@/utils/formatUtil'
import { useSettingStore } from '@/stores/settingStore'
import { useServerConfigStore } from '@/stores/serverConfigStore'
import { storeToRefs } from 'pinia'
import { onMounted, watch } from 'vue'
import { SERVER_CONFIG_ITEMS } from '@/constants/serverConfig'
import { electronAPI } from '@/utils/envUtil'
import { useSettingStore } from '@/stores/settingStore'
import { watch } from 'vue'
const settingStore = useSettingStore()
const serverConfigStore = useServerConfigStore()
const { serverConfigsByCategory, launchArgs, serverConfigValues } =
storeToRefs(serverConfigStore)
const {
serverConfigsByCategory,
serverConfigValues,
launchArgs,
modifiedConfigs
} = storeToRefs(serverConfigStore)
onMounted(() => {
serverConfigStore.loadServerConfig(
SERVER_CONFIG_ITEMS,
settingStore.get('Comfy.Server.ServerConfigValues')
)
})
const revertChanges = () => {
for (const config of modifiedConfigs.value) {
config.value = config.initialValue
}
}
const restartApp = () => {
electronAPI().restartApp()
}
watch(launchArgs, (newVal) => {
settingStore.set('Comfy.Server.LaunchArgs', newVal)

View File

@@ -107,6 +107,14 @@ import { electronAPI as getElectronAPI, isElectron } from '@/utils/envUtil'
// TODO(huchenlei): Add a confirmation dialog.
electronAPI.reinstall()
}
},
{
id: 'Comfy-Desktop.Restart',
label: 'Restart',
icon: 'pi pi-refresh',
function() {
electronAPI.restartApp()
}
}
],

View File

@@ -65,6 +65,12 @@ const messages = {
error: 'Unable to start ComfyUI'
}
},
serverConfig: {
modifiedConfigs:
'You have modified the following server configurations. Restart to apply changes.',
revertChanges: 'Revert Changes',
restart: 'Restart'
},
firstTimeUIMessage:
'This is the first time you use the new UI. Choose "Menu > Use New Menu > Disabled" to restore the old UI.',
download: 'Download',

View File

@@ -3,7 +3,14 @@ import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
export type ServerConfigWithValue<T> = ServerConfig<T> & {
/**
* Current value.
*/
value: T
/**
* Initial value loaded from settings.
*/
initialValue: T
}
export const useServerConfigStore = defineStore('serverConfig', () => {
@@ -11,6 +18,12 @@ export const useServerConfigStore = defineStore('serverConfig', () => {
const serverConfigs = computed(() => {
return Object.values(serverConfigById.value)
})
const modifiedConfigs = computed<ServerConfigWithValue<any>[]>(() => {
return serverConfigs.value.filter((config) => {
return config.initialValue !== config.value
})
})
const serverConfigsByCategory = computed<
Record<string, ServerConfigWithValue<any>[]>
>(() => {
@@ -55,9 +68,11 @@ export const useServerConfigStore = defineStore('serverConfig', () => {
values: Record<string, any>
) {
for (const config of configs) {
const value = values[config.id] ?? config.defaultValue
serverConfigById.value[config.id] = {
...config,
value: values[config.id] ?? config.defaultValue
value,
initialValue: value
}
}
}
@@ -65,6 +80,7 @@ export const useServerConfigStore = defineStore('serverConfig', () => {
return {
serverConfigById,
serverConfigs,
modifiedConfigs,
serverConfigsByCategory,
serverConfigValues,
launchArgs,

View File

@@ -35,6 +35,8 @@ import { useNodeBookmarkStore } from '@/stores/nodeBookmarkStore'
import { useNodeDefStore, useNodeFrequencyStore } from '@/stores/nodeDefStore'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import { useModelStore } from '@/stores/modelStore'
import { useServerConfigStore } from '@/stores/serverConfigStore'
import { SERVER_CONFIG_ITEMS } from '@/constants/serverConfig'
setupAutoQueueHandler()
@@ -151,6 +153,12 @@ const onGraphReady = () => {
// Load keybindings.
useKeybindingStore().loadUserKeybindings()
// Load server config
useServerConfigStore().loadServerConfig(
SERVER_CONFIG_ITEMS,
settingStore.get('Comfy.Server.ServerConfigValues')
)
// Load model folders
useModelStore().loadModelFolders()

View File

@@ -177,7 +177,8 @@ export default {
},
textColor: {
muted: 'var(--p-text-muted-color)'
muted: 'var(--p-text-muted-color)',
highlight: 'var(--p-primary-color)'
}
}
},

View File

@@ -186,4 +186,41 @@ describe('useServerConfigStore', () => {
'test.config3'
])
})
it('should track modified configs', () => {
const configs = [
{
...dummyFormItem,
id: 'test.config1',
defaultValue: 'default1'
},
{
...dummyFormItem,
id: 'test.config2',
defaultValue: 'default2'
}
]
store.loadServerConfig(configs, {
'test.config1': 'initial1'
})
// Initially no modified configs
expect(store.modifiedConfigs).toHaveLength(0)
// Modify config1's value after loading
store.serverConfigById['test.config1'].value = 'custom1'
// Now config1 should be in modified configs
expect(store.modifiedConfigs).toHaveLength(1)
expect(store.modifiedConfigs[0].id).toBe('test.config1')
expect(store.modifiedConfigs[0].value).toBe('custom1')
expect(store.modifiedConfigs[0].initialValue).toBe('initial1')
// Change config1 back to default
store.serverConfigById['test.config1'].value = 'initial1'
// Should go back to no modified configs
expect(store.modifiedConfigs).toHaveLength(0)
})
})

View File

@@ -10,6 +10,9 @@ const mockElectronAPI: Plugin = {
{
tag: 'script',
children: `window.electronAPI = {
restartApp: () => {
alert('restartApp')
},
sendReady: () => {},
onShowSelectDirectory: () => {},
onFirstTimeSetupComplete: () => {},